home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-02-25 | 110.1 KB | 4,737 lines | [TEXT/MPS ] |
- *******************************************************************************
- * IR Request Procedure
- *
- * (C) Copyright Apple Computer, Inc. 1991-1992
- * All rights reserved.
- *
- * by Matt Deatherage
- * October 26, 1991
- *
- * This file contains the code for IR's request procedures, which are what
- * actually do all the work in the new, kinder, gentler, 6.0 version of IR.
- *
- * Modification History:
- *
- * Version Author
- *
- *
- * 2.0a1 Matt Deatherage 11/18/91 (Happy 25th birthday...)
- *
- * First version of this file.
- *
- *
- * 2.0a2 Matt Deatherage 11/25/91
- *
- * 2.0a1 built, 2.0a2 is the first release attempt. Lots and lots of
- * changes to make it work. Mostly little bug fixes not worth mentioning.
- *
- * NDA section almost completely rewritten because the stupid Desk Manager
- * doesn't add DA reference numbers to the menu item at InstallNDA time like
- * any reasonable person would assume. Now we have to extract the address
- * of the init routine and call it ourselves, switching in the direct page and
- * stack we got from InitialLoad2 (or that we allocated) instead of asking
- * CallDeskAcc to send the kiss of life. This is because the stupid (did I
- * say that already?) Desk Manager doesn't put the necessary ID number of an
- * NDA into the header until FixAppleMenu time, and for compatibility I can't
- * blindly call FixAppleMenu. (This is a request proc; the Menu Manager may
- * not even be started for me to allocate a dummy duplicate Apple menu, which
- * might not work anyway.)
- *
- * Preferences reworked because of the new NDA strategy. Both NDA equates
- * and their meanings changed. Now the two options are "Open existing NDAs,"
- * which opens an NDA if it's a duplicate and duplicates aren't supposed
- * to be here; and "Open new NDAs" which does the Apple menu futz and opens
- * the NDA window for newly installed DAs. For a compatibility option, if
- * this bit is _not_ set the DA is just installed and given an initial
- * Shutdown code, but not a startup call, it's not added to the Apple menu
- * and it's not opened. Control titles and ID equates changed to reflect
- * the new changes.
- *
- * Since it turns out we'll have to queue up user IDs not only for killing
- * some Finder Extensions, but also for sending finderSaysHello to anything
- * we've started when we get the next finderSaysIdle message, I added a new
- * mechanism to keep lists of user IDs in handles. Some supporting routines
- * add IDs to the queues and return pointers or handles to them. This is the
- * mechanism we use for these things now. Added routines AddIDToQueue,
- * GetQueuePtr, GetQueueHandle, IRSeesIdle (also added to the request table).
- * Changed KillMyFEs to use the queues instead of hard-coded built-in buffer
- * space.
- *
- * Added new _DebugStr and _SetMileStone macros to the beginning of this file
- * for debugging use. The ones on M16.GSBug are kind of brain-dead; they're
- * just regular tool call macros. The ones in this file let you embed the
- * string as the argument to the macro, like "_DebugStr 'This is a test'".
- * They save A,X,Y and P and generate no code if DebugSymbols is zero, just
- * like the M16.Debug name and procname macros we also use.
- *
- *
- * 2.0a3 Matt Deatherage 12/12/91 (Happy birthday, Dad...)
- *
- * CheckFileAuxType had two missing iny instructions, and Dave suggested
- * rewriting it once I didn't have [<DP],y instructions on the brain. He's
- * right -- lda table,x works much nicer.
- *
- * IRReturnsPreferences was putting the preferences in the _second_ word of
- * the buffer, and RequestProc was happily overwriting them with the $0000 for
- * no error. They're now returned in the third word, like the header files and
- * the comments say.
- *
- * IRGetsAnOpen no longer whooshes back into the icon if you're opening an
- * NDA. It should only refuse to whoosh if the NDA wasn't opened, but right now
- * it doesn't get that information back from askIRToInstall.
- *
- * 2.0a4 Matt Deatherage 12/18/91
- *
- * Several optimizations made at Dave Lyons' suggestion. Stuff like changing
- * "lda localPrefs, ora #preference, sta LocalPrefs" to "lda #preference, tsb
- * LocalPrefs". Some "pei" instructions inserted. Some "stz"s added where
- * they didn't used to be possible due to addressing modes. Little things.
- *
- * IRGetsAnOpen was returning irError codes in the second word of the dataOut
- * buffer, even though it's reserved for finderSaysBeforeOpen and
- * finderSaysOpenFailed. Oops. Now fixed.
- *
- * IRGetsToWork was only checking the low bit of OS_KIND instead of checking
- * for a value of $01. Now it's right.
- *
- * Duplicate-checking code was potentially calling UserShutDown on CDAs or NDAs
- * that accepted the srqGoAway code without removing them from the Desk Manager's
- * lists. Now they're removed, and GS/OS drivers are never given srqGoAway
- * codes since they can't be removed (even if some driver does accept the
- * srqGoAway code). This entailed major changes to UserIDToDAID (formerly
- * UserIDToNDAID) -- it now counts up from 1 looking for DAs instead of
- * assuming there were so many and counting down.
- *
- * Some NDAs are faithfully saving the current cursor when they get an open
- * call and restoring the cursor to that when they're closed. This isn't
- * necessarily a swift idea, because the application's idea of what the cursor
- * should be when the NDA is finally closed may not be related at all to what
- * the cursor was then the DA was opened. Nevertheless, OpenNDAByUserID now
- * calls InitCursor before opening the NDA just in case.
- *
- * IRGetsAnOpen no longer adds things to the NeedsHello queue if askIRToInstall
- * didn't accept the request. It does not reject the open request right now;
- * in a future version it will display an alert saying why the thing couldn't
- * be installed.
- *
- * IRGetsToWork isn't returning errors for requests it doesn't accept anymore.
- * It now accepts the request and returns an IR result code.
- *
- * DoDrivers no longer loses Memory Manager errors when allocating the handle
- * for the DIB structure fails.
- *
- * Queue handles are no longer unlocked during calls to SendRequest.
- *
- * GetPrefsFromDisk now has the same common sense PutPrefsToDisk does -- that
- * is, it closes the file when its done with it.
- *
- * The handle for the preferences pathname is now fixed and no special
- * memory because it never moves. This may change when MakePrefsPath works
- * correctly over AppleShare booting.
- *
- * GetQueuePtr/Handle now uses QueueTable,x (or y) addressing.
- *
- * Still no alert or error windows for the standard IR errors, or comments
- * identifying the machine-generated control source, or proper preference
- * file placing when booting over AppleShare. Stay tuned.
- *
- * 2.0b1 Matt Deatherage 2/19/92
- *
- * RESOURCE FORK ADDED! Wow. An INIT with a resource fork; what stupid idea
- * will I try next. To implement this:
- *
- * % Added GiveMeMyFork to make our resource fork available. If our resource
- * file is open, it just sets the current resource application to IR. If
- * not, it starts the Resource Manager and opens our resource fork. The
- * old resource application is stored on the stack frame so we can be
- * reentrant.
- *
- * % Significant changes to IRDoesPreferences. Now gets the alert string,
- * window template and 320/640 rectangles from resources. They're modified
- * in memory and passed along to the toolbox as appropriate.
- *
- * % Changed IRStartsUp to get the version number and the init icon from the
- * resource fork. Stores the result from VersionString in semi-permanent
- * storage so we don't have to call VersionString more than once.
- *
- * % Added IRNotifyProc so we can close our resource file and zero out our
- * flags that mark it as open. If we just let the Resource Manager do this
- * for us, we never get told that our resource file gets closed.
- *
- * IR now behaves responsibly when you install it and IR is already installed.
- * Specifically, IRStartsUp finds the ID of any existing IRs (by sending the
- * askIRAreYouThere request) and adds it to a new IRQueue. IRSaysIRHere now
- * doesn't respond if we're not done starting up, so we don't answer our own
- * request. The ID of any old IR gets added to a queue that the new IR keeps
- * around. The newly-installed IR tries to kill everything in the IRQueue
- * every chance it gets. The old IR won't go away if it has anything in the
- * NeedsHelloQueue; once it can go away, the new IR kills it.
- *
- * To facilitate all this, KillMyFEs is now 'KillQueueEntries' that sends
- * srqGoAway and calls UserShutDown on every ID in that queue, leaving the
- * items that didn't go away in the queue. This is more generic and works
- * with the kill-old-IRs mechanism.
- *
- * Before moving IR's icon to the resource fork, I fixed the mask so the
- * background doesn't show through where I didn't intend it to.
- *
- * Changed IRSaysIRHere to return the user ID in the second word of the
- * output buffer instead of returning nothing.
- *
- * 2.0b2 Matt Deatherage 2/20/92
- *
- * Changed MakePrefsPath to (finally) work correctly and put the IR.Preferences
- * file in the AppleShare user folder if IR is on an AppleShare volume.
- *
- * Remembered to delete the Notification procedure in IRGoesAway.
- *
- * Changed IRGetsToWork so we don't call RemoveXDA before we send the srqGoAway
- * request -- things that don't accept the request shouldn't be removed!
- *
- * Added DoAlertWindow for easy notification of problem areas, and call it
- * when we try to install Finder Extensions when not in the Finder, and when
- * irDuplicateWontDie would be returned (to ask if another copy is OK). To
- * facilitate this, it makes sense for IRBidsFinderFarewell to actually zero
- * out the FSHDataIn parameter we use to see if we're in the Finder or not,
- * so now it does.
- *
- * Something's still wrong with the notification procedure; when IR is removed
- * with srqGoAway, the system crashes on random OS events. I don't have much
- * of a clue at this point -- it looks OK to me. Haven't spent lots of time
- * debugging it yet.
- *
- * 2.0b3 Matt Deatherage 2/21/92
- *
- * Changed copyright dates to reflect reality.
- *
- * DelNotifyProc wasn't behaving because I was passing the address of the code
- * instead of the address of the notify proc header. Oops. Fixed.
- *
- * Fixed several errors in comments and typos throughout the source.
- *
- * Changed GiveMeMyFork to take no action if we've already changed the current
- * resource app, avoiding a possible reentrancy problem if two routines inside
- * IR called GiveMeMyFork in response to the same user SendRequest.
- *
- * Changed DoAlertWindow to return $FFFF instead of $0000 if something went
- * wrong, since $0000 is a valid button number.
- *
- * Changed all instances of "lda #denyRequest, sta <result" to "stz <result"
- * because it really, really bugs Dave that I wouldn't use stz even when
- * I think the symbolic version is easier to understand.
- *
- * IRRequestProc now accepts no requests if the stack is in page one, since
- * our stack usage combined with any tools we call is likely to make the
- * poor thing overflow.
- *
- * Discovered that askIRToInstall actually was always using your overriding
- * preferences and not just if you set bit zero, as was originally designed.
- * Fixed this to work correctly by keeping a third copy of the preferences
- * in storage, valid only through askIRToInstall.
- *
- * In conjunction with this, changed IRGetsToWork to increment and decrement
- * the IRBusyFlag. Changed IRGetsAnOpen to decrement the busy flag instead
- * of stz'ing it to be more polite.
- *
- * We now no longer kill things that accept srqGoAway but return user ID of
- * zero, because we never were supposed to. Oops.
- *
- * In reshuffling the RemoveXDA code in b2, accidentally left an inaccurate
- * label in @RemoveCDA (inside IRGetsToWork), which made it repeat some stuff
- * in a not useful fashion. Fixed.
- *
- * Changed DoInitsFEs to set the init/FE data bank register to $FF (like
- * GS/OS does) instead of to the init/FE code bank. Yes, badly-written inits
- * will crash faster this way, but we want init authors to find that out.
- *
- * Instead of refusing srqGoAway, we now accept it with user ID zero to say
- * that we can't go away. Dave says this is more correcter.
- *
- * When sending finderSaysGoodbye to our Finder Extensions, we now no longer
- * send with "stopAfterOne" because they might have multiple requests installed
- * with the same user ID.
- *
- * IRSetsPreferences now masks out bit zero before storing in LocalPrefs as
- * well as before putting them to disk.
- *
- * MakePrefsPath correctly preserves the error code after the call to
- * LGetPathname2 now.
- *
- * Changed resource loading code to release resources when we're done using
- * them (unless we pass them to the Toolbox by ID). Changed pointer math
- * on some resources to not worry about bank crossing and changed the resource
- * attributes to specify "noBankCross" to justify this.
- *
- * IRDoesPreferences now exits gracefully if the Window Manager isn't started
- * up, so it won't blow up if you call it from Not The Desktop.
- *
- * 2.0b4 Matt Deatherage 2/23/92
- *
- * If, in the process of installing a new thing, we have to kill the old thing,
- * and if we're also in the Finder, we should send finderSaysGoodbye before
- * sending srqGoAway. We haven't been doing that. Now we are. This is
- * slightly weird, because it means that if something _can't_ go away, we're
- * now sending it finderSaysGoodbye anyway and it will be "invisible" to the
- * user (no Extras menu items, etc.), but still in memory. Even weirder, it
- * will magically "reappear" the next time they launch Finder, giving them
- * perhaps multiple copies of it. People who find this behavior extremely
- * annoying should probably turn on the "Always remove old one" and "Tell me
- * about problems" preferences so IR will tell you when this might happen.
- *
- * But no, it gets worse. We can't send finderSaysGoodbye from within
- * IRGetsToWork (always) because we're often there from finderSaysBeforeOpen
- * (or OpenFailed), in which case the Finder can't respond to whatever the
- * thing we're talking to wants it to do (like remove menu items, etc.). So,
- * unless we were called from our own Idle procedure (so we're _sure_ it's safe
- * to do these things, we queue up things to install in our own Idle procedure
- * and at Idle time, we just call askIRToInstall again. IRGetsToWork doesn't
- * do anything dangerous unless our global "it's idle time!" flag is set.
- * In that case only, it sends finderSaysGoodbye to duplicate extensions and
- * sends all newly-installed things finderSaysHello before returning.
- *
- * 2.0f1 Matt Deatherage 2/25/92 (time flies with deadlines...)
- *
- * IRGetsToWork was setting the busy flag but not checking it. If you'd
- * ever managed to call IRGetsToWork from within an IRGetsToWork, it would
- * blow away the temporary preferences. However, since that was the only
- * reentrancy problem, TempPrefs is now on the stack frame and IRGetsToWork
- * no longer increments or decrements IRBusyFlag. IRGetsAnOpen does, though.
- *
- * I was loading the rAlertString resource for the "About" alert and replacing
- * the rectangle in the string with the correct rectangle before ever calling
- * AlertWindow. But since I was still passing the reference by resource, the
- * Window Manager was disposing of the rAlertString resource and reloading it
- * if you clicked on the version number again. The second time it got the
- * wrong rectangle. There are two ways around this -- either detach the
- * resource and do everything by handle, or make sure the resource doesn't go
- * away until we're definitely done with it. I choose the latter -- I use the
- * new AlertWindow bit to make AlertWindow keep the resource at purge level 3.
- * I set the "locked" bit on the resource to keep it from being purged, and I
- * explictly release the resource at the end of IRDoesPreferences. This works
- * much better.
- *
- * When I fixed the problem that the local preferences could be stored with
- * bit zero set, I accidentally cleared it too soon, so it was never getting
- * set and PutPrefsToDisk wasn't getting called, even on a "save" in the
- * preferences dialog. Now fixed.
- *
- * The window template for the preferences window was being loaded unlocked
- * (so it can be purged) and I was making toolbox calls that could move
- * memory after dereferencing it but before using it. The window resource
- * is now marked "locked" in the resource file, and before leaving the
- * IRDoesPreferences routine, I reload the resource (returning the same
- * locked handle) and release it to level $FFFF, disposing it instantly.
- *
- * At Dave's request, if you have your preferences set to "Always kill old
- * copies" and you encounter one that won't go away, pressing the option key
- * while clicking "Install another copy" makes IR forcibly shut down the old
- * one anyway. This is very dangerous unless you know what you're doing so
- * it may or may not make it into the Read.me file. Aren't you glad you
- * read all these comments?
- *
- * askIRAreYouThere (IRSaysIRHere) now returns the version longword from our
- * resource fork in +004 through +007 of the dataOut buffer. This is kept from
- * boot time in the IRVersion global variable so we don't have to do it again.
- *
- * MakePrefsPath now creates the file in the same directory as the IR
- * file even on AppleShare if GetUserPath returns an error. This helps in
- * the slightly-pathological-which-is-why-I-use-it case of launching it from
- * a server that has no user volume, as long as you have write privileges
- * to the IR folder. (My server isn't an Apple II boot server, but the same
- * is true for System 7 File Sharing.)
- *
- * IRGetsToWork now actually respects the irNoDuplicates flag -- if it's clear,
- * it doesn't mess with trying to remove or shut down duplicates at all. It
- * bypasses all that stuff and goes directly to loading a new copy.
- *
- * IRGoesAway was duplicating the functionality of IRBidsFinderFarewell --
- * which means we could be removing our own Finder Extras menu item more
- * than once. Since we're supposed to get finderSaysGoodbye before
- * srqGoAway, the duplicate code in srqGoAway is now gone.
- *
- * There's a significant problem in trying to kill duplicate anythings that
- * install Finder request procedures, by design. If we have to try to kill
- * a duplicate while in the Finder, we're required to send the duplicate a
- * finderSaysGoodbye request before we send srqGoAway. However, if the original
- * can't accept srqGoAway for whatever reason, it's already seen our
- * finderSaysGoodbye request. It will eventually get a second one, either from
- * the Finder or from us again if someone tries to double-click that file
- * again and irNoDuplicates is set. This can cause serious problems. For
- * example, EasyMount zeroes out its Extras menu item ID global variable,
- * and if it gets a second finderSaysGoodbye code, it makes a request to
- * tellFinderRemoveFromExtras with a zero menu item ID. This makes the Finder
- * remove the "About the Finder..." menu item. Ack.
- *
- * There really isn't a way around this -- even keeping a list of all the things
- * I have that I couldn't kill won't prevent the Finder from sending duplicate
- * finderSaysGoodbye codes. The only options are:
- *
- * a) Don't send finderSaysGoodbye before srqGoAway -- not acceptable.
- * b) Invent an srqCanYouGoAway code -- too late for EasyMount and others.
- * c) Require everyone to accept multiple finderSaysGoodbye requests without
- * causing damage -- too late for EasyMount
- * d) Require everyone to always act on srqGoAway -- not feasible.
- *
- * So, the real compromise solution is a combination of c) and d). We'll document
- * that your Finder Extension must either always act on srqGoAway or must accept
- * multiple finderSaysGoodbye requests harmlessly. Failure to do so is now
- * chalked up as a "bug" in EasyMount. To work around this from a user
- * standpoint, set the "Always kill duplicates" radio button and hold down the
- * option key when clicking "Install another copy." I guess this does have to
- * go into the documentation now.
- *
- * 2.0 Matt Deatherage 02/25/92
- * Changed DebugSymbols to zero to remove all procedure names and any left over
- * _DebugStr or _SetMileStone macros.
- *
- *******************************************************************************
-
- INCLUDE 'E16.IR'
- INCLUDE 'M16.Util2'
- INCLUDE 'E16.Locator'
- INCLUDE 'M16.Locator'
- INCLUDE 'M16.MiscTool'
- INCLUDE 'E16.GSOS'
- INCLUDE 'M16.GSOS'
- INCLUDE 'E16.Loader'
- INCLUDE 'M16.Loader'
- INCLUDE 'M16.Window'
- INCLUDE 'E16.Window'
- INCLUDE 'M16.Control'
- INCLUDE 'M16.Debug'
- INCLUDE 'E16.Event'
- INCLUDE 'M16.Memory'
- INCLUDE 'M16.Desk'
- INCLUDE 'E16.Desk'
- INCLUDE 'M16.QDAux'
- INCLUDE 'E16.Finder'
- INCLUDE 'M16.QuickDraw'
- INCLUDE 'M16.Menu'
- INCLUDE 'M16.Resources'
- INCLUDE 'E16.Resources'
-
- *******************************************************************************
- *
- * Revised _DebugStr and _SetMileStone macros for our use
- *
- *******************************************************************************
-
- MACRO
- &lab _DebugStr &s
- &lab
- if DebugSymbols<>0 then
- php
- pha
- phx
- phy ; save the registers
- pea @string>>16
- pea |@string
- ldx #$09FF
- jsl $E10000
- ply
- plx
- pla
- plp
- bra @pastString
- @String str &s
- @PastString
- endif
- mend
-
- MACRO
- &lab _SetMileStone &s
- &lab
- if DebugSymbols<>0 then
- php
- pha
- phx
- phy ; save the registers
- pea @string>>16
- pea |@string
- ldx #$0AFF
- jsl $E10000
- ply
- plx
- pla
- plp
- bra @pastString
- @String str &s
- @PastString
- endif
- mend
-
-
- *******************************************************************************
- *
- * Equates for within the request procedures
- *
- *******************************************************************************
-
- DebugSymbols equ 0 ; for inline procedure names
-
- DefineStack
-
- ;
- ; Stuff that we allocate as local variables in the request proc
-
-
-
- PrefsWindPtr Long ; pointer to preferences window when up
- MyDPageFlag Word ; flag to indicate I allocated bank zero memory
- FilePointer Long ; GS/OS string pointer to the file we're going to
- ; load
- TempPrefs Word ; temporary preferences for IRGetsToWork
- OldResourceApp Word ; previous resource application
- ThisInitID Word ; user ID of the thing we're working on
- StartAddress Long ; address where the thing got loaded
- DPagePtr Word ; address of its direct page space
- DPageSize Word ; size of direct page/stack segment
- DIBPtr Long ; pointer to the DIB for installing GS/OS drivers
- Filetype Word ; filetype of what we're after
- Auxtype Word ; auxtype of what we're after
- ; (see IRData for explanation of word vs. long)
- Temp Long ; temporary storage and deref
- TempAlso Long ; more of the same
-
- SizeLocals EndLocals
-
- ;
- ; Registers we save and the RTL address
- ;
-
- OldDBR Byte
- OldDP Word
- RTLAddr Block 3
-
- BegParms
-
- ;
- ; Parameters to the request procedure
- ;
-
- DataOut Long
- DataIn Long
- RequestCode Word
-
- SizeParms EndParms
-
- ;
- ; The result from the routine
- ;
-
- Result Word
-
- SizeEverything EndLocals
-
- ;
- ; Private equates to building (but not using) IR. First, GS/OS and system
- ; equates.
- ;
-
- InitID equ $A000 ; setup file user ID
- DAID equ $5000 ; DA user ID
- DriverID equ $3900 ; driver user ID
- SupDrvrID equ $3A00 ; supervisory driver ID
- INSTALL_DRIVER equ $01FCA8 ; System Service call
- warm_cold_flag equ $E101D0 ; bit 0 = 0 if cold startup
- BUSYFLAG equ $E100FF ; system busy flag (one byte)
- OS_KIND equ $E100BC ; currently active OS (one byte)
- OS_BUSY equ $E100BE ; word, bit 15 = 1 if GS/OS is busy
- KEYMODREG equ $E0C025 ; keyboard modifiers register
-
- ;
- ; Equates for IR's private queue mechanism
- ;
-
- startIDCount equ 20 ; number of user IDs in queues by default
- FinderExtQueue equ 0
- NeedsHelloQueue equ 1
- IRQueue equ 2
- DelayedStartQueue equ 3
- lockQueueHandle equ $8000 ; add this to queue number to lock handle
-
- sizeOfFTEntry equ 8 ; eight bytes per entry in file type table
-
- ;
- ; Equates for resource IDs in our resource fork
- ;
-
- IR_Init_Icon equ $1 ; rIcon
-
- Preferences_Ctl_List equ $1003 ; rControlList
-
- PSTR_00000001 equ $1 ; rPString
- PSTR_00000002 equ $2
- PSTR_00000003 equ $3
- PSTR_00000004 equ $4
- PSTR_00000005 equ $5
- PSTR_00000006 equ $6
- PSTR_00000007 equ $7
- PSTR_00000008 equ $8
- PSTR_00000009 equ $9
- PSTR_0000000A equ $A
- PSTR_0000000B equ $B
- PSTR_0000000C equ $C
- PSTR_0000000D equ $D
-
- Preferences_LEText equ $1 ; rTextForLETextBox2
- Permanently_LEText equ $2
- If_duplicate_LEText equ $3
- LETXTBOX_00000005 equ $5
- About_LEText equ $6
-
- Preferences_Window equ $FFA ; rWindParam1
-
- irDuplicateWontDieAlert equ $1 ; rAlertString
- irAboutAlert equ $2
- irNoFinderAlert equ $3
- irBusyAlert equ $4
-
- IR_Version equ $1 ; rVersion
-
- Comment1 equ $1 ; rComment
- Comment2 equ $2
-
- TitleID equ $1 ; Control IDs
- OpenNewNDAID equ $2
- FinderExtID equ $3
- PermanentlyID equ $4
- RadioPromptID equ $5
- InstallNewID equ $6
- TryKillOldID equ $7
- AlwaysKillOldID equ $8
- VersionID equ $9
- AcceptID equ $B
- CancelID equ $C
- SaveID equ $D
- CopyExistNDAsID equ $E
- DoBeforeOpenID equ $F
- DoAlertsID equ $10
- UnderlineRectID equ $11
- RadioRectID equ $12
-
- WindowRects equ $1 ; rTwoRects
-
- EJECT
- *******************************************************************************
- *
- * Static and private data for IR
- *
- *******************************************************************************
-
- IRData RECORD EXPORT
-
- IRUserID dc.w 0 ; IR's user ID
- IRBusyFlag dc.w 0 ; non-zero if we're busy
- IRResFile dc.w 0 ; reference number for our resource fork
-
- ;
- ; This is the filetype table for filetypes we can feed to askIRToInstall. We
- ; do this so we don't have to hard-code it in both askIRToInstall as well as
- ; finderSaysBeforeOpen and finderSaysOpenFailed.
- ;
- ; The table includes only word-value auxtypes, giving us a slight optimization
- ; by "knowing" that any auxtype with a non-zero high word is unacceptable. See
- ; CheckFileAuxType.
- ;
- ; The four values are filetype, auxtype mask, auxtype and user ID. Most of the auxtype
- ; masks and auxtypes are 0, so an AND #0, CMP #0 on an auxtype will always return
- ; TRUE. Putting the User ID here really simplifies dispatching, but it does mean
- ; that we'll have to rework this if we ever need one file type to have two possible
- ; user ID ranges.
- ;
-
- FTTableCount dc.w (endFileTypeTable-fileTypeTable)/sizeOfFTEntry
- ; that's a count, son
- FTTableSize dc.w endFileTypeTable-fileTypeTable
- fileTypeTable dc.w PermInitType,0,0,InitID
- dc.w TempInitType,0,0,InitID
- dc.w NDAType,0,0,DAID
- dc.w CDAType,0,0,DAID
- dc.w DriverType,DriverAuxMask,DriverAuxType,DriverID
- dc.w GenLoadType,FindExtAuxMask,FindExtAuxType,InitID ; for now
- endFileTypeTable
-
- FinderString str 'Apple~Finder~'
- EXPORT IRString, ID1, ID2
- IRString dc.b IRStringEnd-IRString-1
- dc.b 'Apple~IR~'
- ID1 dc.b 'xx'
- ID2 dc.b 'xx~'
- IRStringEnd equ *
- IRShortString str 'Apple~IR~'
-
-
- ;
- ; Here's a copy of the finderSaysHello dataIn pointer
- ;
-
- FSHdataIn ds.l 1
-
- ;
- ; This is the buffer for tellFinderAddToExtras
- ;
-
- AddToXtras dc.w 0 ; recvCount
- ATXresult dc.w 0 ; result code
- ATXItemID dc.w 0 ; item ID assigned by Finder
- ATXExtrasID dc.w 0 ; extras menu ID
-
- ;
- ; Here are the stored direct page and stack pointer for transferring to Inits and FEs
- ;
-
- MyDP ds.w 1
- MyStack ds.w 1
-
- ScreenRect dc.w 0,0,200,640 ; for whooshing (in Finder only)
-
- IRBootString dc.b 'IR '
- IRBootVersion dc.b ' ' ; ten spaces
- dc.b 0
- VersionLength dc.w 0
- IRVersion dc.l 0 ; our version longword from our resource fork
-
- ;
- ; Here's an extended task record for our DoModalWindow call
- ;
-
- MyTaskRec
- EventWhat ds.B 2
- EventMessage ds.B 4
- EventWhen ds.B 4
- EventWhere ds.B 4
- EventModifiers ds.B 2
- TaskData ds.B 4
- TaskMask dc.L $001FFFFF ; that's everything we want
- LastClickTick ds.B 4
- ClickCount ds.B 2
- TaskData2 ds.B 4
- TaskData3 ds.B 4
- TaskData4 ds.B 4
- LastClickPtY ds.B 2
- LastClickPtX ds.B 2
-
-
- ;
- ; The preferences are stored as one word, defined as:
- ; ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____
- ; | | | | | | | | | | | | | | | | |
- ; | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
- ; |____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|____|
- ;
- ; |__________________________________| | | | | | | | |
- ; | | | | | | | | |
- ; Reserved | | | | | | | |
- ; | | | | | | | |
- ; 1 = don't alert user to problems --------+ | | | | | | |
- ; 1 = Wait for openFailed to do Finder stuff ---+ | | | | | |
- ; 1 = Open this NDA if possible ---------------------+ | | | | |
- ; 1 = kill this Finder Extension on quitting -------------+ | | | |
- ; 1 = don't futz with Apple Menu to install NDAs --------------+ | | |
- ; 1 = return error if duplicate can't be killed --------------------+ | |
- ; 1 = return error if duplicate exists ----------------------------------+ |
- ; Reserved ---------------------------------------------------------------+
- ;
- ; Now, truthfully, I could take more than one word to store all this stuff, but
- ; I don't really have a good reason to -- if I put each one in a separate word, it
- ; would require one fewer AND instruction per preference check -- but this makes it
- ; easy for any caller to the IR request procedure to override any preference. That's
- ; also cool.
- ;
- ; We keep three copies -- the disk preferences and the local preferences. Each time we
- ; get the preferences passed, we put them in the local copy unless we're instructed
- ; to write them to disk. The temporary preferences are in effect only through
- ; askIRToInstall and are kept on the stack frame, not here.
- ;
- DiskPrefs dc.w 0
- LocalPrefs dc.w 0
-
- ;
- ; Parameter blocks for creating, opening, read/writing and closing the preferences file
- ;
-
- CreateParms dc.w 4 ; parameter count
- CreatePath dc.l 0 ; pointer to filename
- dc.w $83 ; no rename -- file name is hard-coded
- dc.w IRPrefsType ; filetype
- dc.l IRPrefsAuxType ; auxtype
-
- RWParms dc.w 4
- RWrefnum dc.w 0 ; reference number
- buffer dc.l DiskPrefs ; buffer pointer
- reqCount dc.l 2 ; request count
- transferCount dc.l 0 ; transfer count
-
- CloseParms dc.w 1
- CloseRefNum dc.w 0 ; reference number
-
- OpenParms dc.w 3
- OpenRefNum dc.w 0 ; reference number
- OpenPath dc.l 0 ; pointer to filename
- OpenAccess dc.w 0 ; requested access
-
- PrefsPathPtr dc.l 0 ; pointer to our prefs pathname
- PrefsFileName str ':IR.Preferences'
-
- DInfoParms dc.w 4 ; pCount
- DInfoDevNum dc.w 1 ; device #1
- DInfoDevName dc.l NoName ; don't want a name
- DInfoCharacteristics dc.w 0 ; characteristics
- DInfoBlocks dc.l 4 ; block count
-
- NotifyProcParms dc.w 1 ; pCount
- IMPORT IRNotifyProc
- NotifyProcPtr dc.l IRNotifyProc
-
- NoName dc.l 0 ; zero buffer length
-
- UserPathParms dc.w 3 ; pCount
- dc.w AppleShareFSID ; file system ID
- dc.w 8 ; command == GetUserPath
- UserPathPtr dc.l 0 ; pointer to user path
-
- GFIParms dc.w 8 ; enough to get the option list
- GFIPathPtr dc.l 0 ; pathname pointer
- dc.w 0 ; access
- GFIFileType dc.w 0 ; filetype
- GFIAuxType dc.l 0 ; auxtype
- dc.w 0 ; storage type
- ds.b 16 ; 16 bytes for dates/times
- dc.l GFIOptionList ; option list pointer
-
- GFIOptionList dc.w $2E
- OptionListReqSize dc.w 0 ; output size
- OptionListFSID dc.w 0 ; file system ID
- ds.b $30 ; storage space for stuff we don't read
-
- srqOutBuffer dc.w 0 ; recvCount
- srqResultID dc.w 0 ; resulting user ID
- srqFlags dc.w 0 ; flags
-
- ;
- ; This is the table of handles for the queues we have. We identify queues with
- ; a zero-based count -- zero refers to the first pointer, 1 refers to the second,
- ; etc. Call AddIDToQueue to add a user ID to one of these, but just dereference
- ; and use them when necessary.
- ;
-
- QueueTable
-
- FETable dc.l 0 ; Finder Extensions to kill
- FSHTable dc.l 0 ; Code that needs finderSaysHello calls
- IRTable dc.l 0 ; list of IRs that need to be killed
- DelayedStartTable dc.l 0 ; list of things that need to be done at Idle
-
-
- ;
- ; This is the global flag that tells IRGetsToWork that it's being called from
- ; finderSaysIdle; that means it's OK to actually really truly install things
- ; because it's OK to send finderSaysGoodbye to duplicates that may exist.
-
- IdleGlobalFlag dc.w 0
-
- ;
- ; Here's the menu item template for the Extras menu item.
- ;
-
- PrefsItem dc.w $8000 ; set bit fifteen to say add dividing line above
- PrefsID dc.w 0 ; Finder tells us this
- dc.w 0 ; FEs shouldn't have hard-coded key equivalents
- dc.w 0 ; no check item
- dc.w 0 ; ref by pointer, no styles
- dc.l PrefsItemName ; preferences item name
-
- PrefsItemName str 'IR Preferences…'
-
- EndR
-
- EJECT
- *******************************************************************************
- *
- IRRequestProc PROCNAME EXPORT
- *
- * Description: This is the request procedure passed to AcceptRequests
- * by IR. It handles all the requests we accept, both
- * from the Finder and from IR itself.
- *
- * The Finder will send us all the Finder requests, which we accept and respond
- * to as you might expect. For example, we accept finderSaysHello and respond
- * with tellFinderAddToExtras for our preferences dialog, etc.
- *
- * However, we also accept a special request to "IR" any of the kinds of
- * documents IR accepts (DAs, Inits, GS/OS drivers and Finder extensions at
- * this writing). When we determine we need to do something with an IR-able
- * file, we just call SendRequest to ask ourself to do it.
- *
- * It sounds weird, but it allows us to put all the work into this procedure and
- * let the IR application (or other people) call us. All we have to do is take
- * a little care to be re-entrant and it all works just fine.
- *
- * We do our private setup before dispatching just for general health.
- *
- * By the way, if most of this routine looks kind of familiar, don't strain
- * yourself trying to figure out why. The stack setup and teardown is lifted
- * almost verbatim from the DTS Sample Code tool FakeModalDialog, and the table
- * dispatch for the requests we accept comes from the assembly shell's event-
- * dispatching routine. If code works, there's no need to rewrite it.
- *
- * Inputs: reqCode (word) -- the request code
- * dataIn (long) -- pointer to input data
- * dataOut (long) -- pointer to output data
- *
- * Outputs: Besides filling in dataOut:
- * result (word) -- set bit 15 if we accept the request
- *
- * External Refs:
- IMPORT IRGreetsFinder
- IMPORT IRBidsFinderFarewell
- IMPORT IRGetsAnOpen
- IMPORT IRLooksAtExtras
- IMPORT IRGoesAway
- IMPORT IRStartsUp
- IMPORT IRSaysIRHere
- IMPORT IRGetsToWork
- IMPORT IRReturnsPreferences
- IMPORT IRSetsPreferences
- IMPORT IRDoesPreferences
- IMPORT IRSeesIdle
- IMPORT KillQueueEntries
- WITH IRData
- *
- * Entry Points: None.
- *
- *******************************************************************************
-
- ;
- ; Since we use a fair amount of stack space, don't accept any requests
- ; if the stack is in page one. Dave says <result is pre-zeroed for us,
- ; so if the stack is in page one just strip the input parameters and
- ; get out of here.
- ;
-
- tsc
- and #$FF00
- xba ; stack page now in low byte of A
- dec a
- beq StripInputParms ; skip everything if we were in page one stack
-
- phb ; save the data bank register
- phk
- plb ; set the DBR to our code bank
- phd ; save direct page register.
- tsc ; make space for locals.
- sec
- sbc #sizeLocals
- tcs
- tcd ; Set direct page register.
-
- stz <result ; this isn't defined on entry
- stz <OldResourceApp ; so we can keep it straight
-
- lda IRTable
- ora IRTable+2
- beq @DoTheRequest ; kill this queue if a pointer exists
- lda #0 ; no finderSaysGoodbye
- ldx #IRQueue
- jsr KillQueueEntries
-
- @DoTheRequest lda <RequestCode
- ldx #endRequestTable-RequestTable-4
- checkNextCode cmp RequestTable,x ; are we handling this request?
- beq doRoutine ; yes, then call a routine
- dex ; no, then keep checking
- dex
- dex
- dex
- bpl checkNextCode ; keep scanning table
-
- bra notAccepted ; not a request we take, so politely refuse
-
- doRoutine lda #$8000 ; we're going to accept this request
- sta <result
-
- jsr (RequestTable+2,x) ; call the routine
-
- ;
- ; We assume that the request procedure has filled in all the buffers and left
- ; any error code in A. Since not all routines store result codes, we only
- ; put something in [<dataOut],2 if the carry flag is set. That applies to
- ; zero (no error) results as well.
- ;
-
- bcc noStoreError ; skips storing the error
- ldy #2
- sta [<dataOut],y ; save error code.
-
- noStoreError lda <OldResourceApp ; did we change this?
- beq noResAppChange ; as if we never did anything
-
- pha
- _SetCurResourceApp
-
- noResAppChange ; same place as
- notAccepted tdc ; get rid of local variables.
- clc
- adc #sizeLocals
- tcs
- pld ; restore direct page register
- plb ; restore data bank register
-
- stripInputParms lda 1,s ; move return address.
- sta 1+sizeParms,s
- lda 2,s
- sta 2+sizeParms,s
-
- tsc ; pull passed parms off stack.
- clc ; carry is already cleared if stack
- adc #sizeParms ; isn't in page one.
- tcs
-
- rtl
-
-
- ;
- ; Since the dispatch code searches the entire table, we can add or subtract
- ; lines as necessary to add or delete requests we accept. This is Handy.
- ;
-
- RequestTable
- dc.w finderSaysHello, IRGreetsFinder ; *
- dc.w finderSaysGoodbye, IRBidsFinderFarewell ; *
- dc.w finderSaysBeforeOpen, IRGetsAnOpen ; *
- dc.w finderSaysOpenFailed, IRGetsAnOpen ; *
- dc.w finderSaysIdle, IRSeesIdle
- dc.w finderSaysExtrasChosen,IRLooksAtExtras ; *
- dc.w srqGoAway, IRGoesAway ; *
- dc.w askIRStartUp, IRStartsUp ; *
- dc.w askIRAreYouThere, IRSaysIRHere ; *
- dc.w askIRToInstall,IRGetsToWork ; *
- dc.w askIRGetPrefs, IRReturnsPreferences ; *
- dc.w askIRSetPrefs, IRSetsPreferences ; *
- dc.w askIRDoPrefs, IRDoesPreferences ; *
-
- endRequestTable
-
- EndP
-
- EJECT
- *******************************************************************************
- *
- IRGreetsFinder PROCNAME
- *
- * Description: Our response to finderSaysHello, we add our menu item to
- * the Extras menu.
- *
- *
- * Inputs: None
- *
- * Outputs: None
- *
- * External Refs:
-
- import IRData
- with IRData
- *
- * Entry Points:
- *
- *******************************************************************************
-
- lda <dataIn
- sta FSHdatain
- lda <dataIn+2
- sta FSHdatain+2 ; copy this for our use
-
- pushword #tellFinderAddToExtras
- pushword #sendToName+stopAfterOne
- pushlong #FinderString
- pushlong #PrefsItem
- pushlong #AddToXtras
- _SendRequest
-
- clc
- rts
-
- EndP
-
-
- EJECT
- *******************************************************************************
- *
- IRBidsFinderFarewell PROCNAME
- *
- * Description: Our response to finderSaysGoodbye; we kill any Finder
- * extensions we have to kill and go away.
- *
- *
- * Inputs: None
- *
- * Outputs: None
- *
- * External Refs:
- with IRData
- import KillQueueEntries
- *
- * Entry Points:
- *
- *******************************************************************************
-
- ;
- ; Do nothing if we're not actively in the Finder!
- ;
-
- lda FSHDataIn
- ora FSHDataIn+2
- bne @KillFEQueue
- stz <result ; deny this request
- bra @OverAndOut
-
- @KillFEQueue lda #0
- ldx #FinderExtQueue
- jsr KillQueueEntries ; they've all gotten finderSaysGoodbye
-
- pushword #tellFinderRemoveFromExtras
- pushword #sendToName+stopAfterOne
- pushlong #FinderString
- pea 0
- pushword ATXItemID
- pushlong #AddToXtras ; same buffer will do
- _SendRequest
-
- stz FSHDataIn
- stz FSHDataIn+2
-
- @OverAndOut clc
- rts ; that's all we gotta do.
- ; (ain't subroutines neat?)
- EndP
-
- EJECT
- *******************************************************************************
- *
- IRGetsAnOpen PROCNAME
- *
- * Description: This is the brunt of the Finder work; we come here on
- * BeforeOpen and OpenFailed and do the real work here if
- * it's appropriate.
- *
- *
- * Inputs: dataIn as passed by Finder
- *
- * Outputs: None
- *
- * External Refs:
- with IRData
- import CheckFileAuxType
- IMPORT AddIDToQueue
- *
- * Entry Points:
- *
- * Notes:
- *
- * 2.0a4 -- MD
- * I leave the errors in the accumulator so you can see which errors I would
- * return and why, but GotOpenOut now properly _clears_ the carry flag so the
- * RequestProc doesn't store the result code in the second word of the dataOut
- * buffer, since it is (after all) reserved.
- *
- *******************************************************************************
-
- ;
- ; This routine is not re-entrant, so we check to make sure we're not busy
- ; doing something else first.
- ;
-
- lda irBusyFlag
- bne @Busy
-
- inc irBusyFlag
- bra @CheckType
-
- @Busy stz <result ; denying the request
- lda #irBusy
- brl GotOpenOut1
-
- ;
- ; Even though IRGetsToWork does type checking, we need to do the same thing so
- ; we can know if we need to "zoom" out or not before getting anything done.
- ; But first, we see if this is the request we're supposed to be acting on
- ; and pass if it's not.
- ;
-
- ; This is kind of skanky but more efficient than other ways...
-
- @CheckType ldy #16
- lda [<dataIn],y ; the modifiers
- and #controlKey ; non-zero if control was down
- pha ; store on stack
-
- lda LocalPrefs
- and #irWaitOpenFailed
- lsr a
- lsr a
- xba
- ;
- ; This is an efficient way to do this but it depends on illicit knowledge
- ; that irWaitOpenFailed is the sixth bit of the preferences word.
- ;
-
- eor 1,s
- and #controlKey
- sta 1,s
-
- ;
- ; After that little trick, 1,s contains $0000 if and only if both the Control
- ; key was down _and_ the irWaitOpenFailed bit was set, or if neither was.
- ; Those circumstances are when we accept the request if it's
- ; finderSaysBeforeOpen, and when we reject the request if it's
- ; finderSaysOpenFailed.
- ;
-
- lda <requestCode
- cmp #finderSaysBeforeOpen
- bne @ItsOpenFailed
-
- @ItsBeforeOpen pla
- beq @DoItNow
- stz <result ; denying the request
- brl GotOpenOut
-
- @ItsOpenFailed pla
- bne @DoItNow
- stz <result ; denying the request
- brl GotOpenOut
-
-
- @DoItNow ldy #10
- lda [<dataIn],y ; filetype
- pha
- iny
- iny
- lda [<dataIn],y ; auxtype low word
- pha
- iny
- iny
- lda [<dataIn],y ; auxtype high word
- tay
- plx
- pla
- jsr CheckFileAuxType
- bcc @CheckPrinting
-
- stz <result ; denying the request
- lda #irNotIRFile ; tell the caller we can't do it
- brl GotOpenOut
-
- ;
- ; Look to see if the document was "opened" or "Printed" -- it doesn't make sense
- ; for IR to accept "Print" requests.
- ;
-
- @CheckPrinting ldy #22 ; offset to open/print flag in parameters
- lda [<dataIn],y
- beq @KeepGoing
- stz <result ; denying the request
- lda #irCantPrint
- brl GotOpenOut
-
- ;
- ; OK, we're going to do it. Zoom out and call IR's request proc to do the work.
- ;
-
- @KeepGoing pushlong #$80000000
- pushlong [<dataIn],6 ; a nifty feature I rarely use
- pushlong #ScreenRect
- _WhooshRect
-
- lda LocalPrefs
- sta OurFlags
- ldy #2
- lda [<dataIn],y
- sta OurFilePtr
- iny
- iny
- lda [<dataIn],y
- sta OurFilePtr+2
- ldy #10
- lda [<dataIn],y
- sta OurFileType
- iny
- iny
- lda [<dataIn],y
- sta OurAuxType
- iny
- iny
- lda [<dataIn],y
- sta OurAuxType+2
-
- pushword #askIRToInstall
- pushword #sendToName+stopAfterOne
- pushlong #IRString
- pushlong #OurDataIn
- pushlong #OurDataOut
- _SendRequest
-
- ;
- ; 2.0a4 -- check to see if the request was accepted before adding it to the
- ; NeedsHello queue.
- ;
-
- lda OurIRError
- bne @SkipHelloQueue
-
- ;
- ; Since we're in the Finder, and the Finder can't respond to most requests during
- ; BeforeOpen or OpenFailed, we queue the user ID in the NeedsHello queue so we
- ; can send finderSaysHello during the next finderSaysIdle message.
- ;
-
- @AddToHelloQueue lda OurUserID
- ldx #NeedsHelloQueue
- jsr AddIDToQueue
-
- ;
- ; That's all this guy needs to do, except zoom out and return any result code
- ; 2.0a3 -- everyone but me thinks whooshing back in on NDAs is weird, so now
- ; we don't any more.
- ;
-
- @SkipHelloQueue lda OurFileType
- cmp #NDAType
- beq GotOpenOut
-
- @DoWhooshIn pushlong #$00000000
- pushlong [<dataIn],6 ; a nifty feature I rarely use
- pushlong #ScreenRect
- _WhooshRect
-
- GotOpenOut dec irBusyFlag
- GotOpenOut1 clc ; we branch here if we were busy
- rts
-
- OurDataIn
- OurFlags dc.w 0 ; flags
- OurFilePtr dc.l 0 ; file name pointer
- OurFileType dc.w 0 ; file type
- OurAuxType dc.l 0 ; auxtype
-
- OurDataOut
- OurRecvCount dc.w 0
- OurIRError dc.w 0
- OurUserID dc.w 0
-
- EndP
-
- EJECT
- *******************************************************************************
- *
- IRLooksAtExtras PROCNAME
- *
- * Description: Our answer to finderSaysExtrasChosen, we see if it's the
- * IR preferences dialog and if so, send the request to
- * askIRDoPrefs. Fortunately, that takes no parameters so
- * we don't have to worry about reentrancy.
- *
- *
- * Inputs: from Finder.
- *
- * Outputs: None
- *
- * External Refs:
- with IRData
- *
- * Entry Points:
- *
- *******************************************************************************
-
- lda <dataIn
- cmp ATXItemID
- beq @ItsOurID
-
- stz <result ; we're not taking the request after all
- bra @NotOurID
-
- @ItsOurID pushword #askIRDoPrefs
- pushword #sendToName+stopAfterOne
- pushlong #IRString
- lda #0
- pha
- pha ; no dataIn
- pha
- pha ; no dataOut
- _SendRequest
-
- @NotOurID clc
- rts
-
- EndP
-
- EJECT
- *******************************************************************************
- *
- IRStartsUp PROCNAME
- *
- * Description: This request code starts up IR. Provided so the request
- * procedure can be completely separate of all the other parts
- * of the IR package that call it. Starts things and displays
- * the boot info with ShowBootInfo.
- *
- *
- * Inputs: dataIn is a pointer to the following:
- * word: user ID
- *
- *
- * Outputs: None.
- *
- * External Refs:
- WITH IRData
- IMPORT GetPrefsFromDisk
- IMPORT AddIDToQueue
- IMPORT GiveMeMyFork
- IMPORT IRNotifyProc
- *
- * Entry Points: None.
- *
- *******************************************************************************
-
- stz IRUserID ; for safety
-
- ;
- ; See if another IR is present. Since we won't accept the request
- ; until our user ID is non-zero, we can call askIRAreYouThere until we
- ; get an error, adding the resulting user ID to the IRQueue each time.
- ;
-
- @FindIRLoop pea askIRAreYouThere
- pea sendToName+stopAfterOne
- pushlong #IRShortString
- lda #0
- pha
- pha ; dataIn == NIL
- pushlong #OurBuffer
- _SendRequest
- php ; save this in case I forget to later
-
- lda [<dataIn] ; the user ID
- sta IRUserID ; keep it for a while
-
- plp
- bcs @NoMoreIRs
- lda TargetID
- ldx #IRQueue
- jsr AddIDToQueue
-
- ;
- ; Display the boot info
- ;
-
- @NoMoreIRs jsr GiveMeMyFork
-
- pha
- pha ; space for result
- pushword #rVersion
- pushlong #IR_Version
- _LoadResource
- pulllong <Temp
- lda [<Temp]
- tax
- ldy #2
- lda [<Temp],y
- sta <Temp+2
- stx <Temp ; temp points to version resource
-
- lda #0
- pha ; flags
- lda [<temp],y ; high word of version number (Y still = 2)
- pha
- sta IRVersion+2
- lda [<temp]
- pha
- sta IRVersion
- pushlong #IRBootVersion
- _VersionString
-
- pushword #$FFFF ; release now
- pushword #rVersion
- pushlong #IR_Version
- _ReleaseResource ; we're done with this for good
-
- lda IRBootVersion ; first word of buffer
- and #$00FF ; make it a word
- sta VersionLength ; for later use
-
- lda IRBootVersion
- and #$FF00 ; clear low byte (first character)
- ora #'v' ; put 'v' in first character
- sta IRBootVersion ; now the string for ShowBootInfo is right
-
- pha
- pha ; space for result
- pushword #rIcon
- pushlong #IR_Init_Icon
- _LoadResource
- pulllong <Temp
- lda [<Temp]
- tax
- ldy #2
- lda [<Temp],y
- sta <Temp+2
- stx <Temp ; Temp points to icon in memory
-
- pushlong #IRBootString
- pei <Temp+2
- pei <Temp ; pointer to icon
- _ShowBootInfo
-
- pushword #2 ; purge level 2
- pushword #rIcon
- pushlong #IR_Init_Icon
- _ReleaseResource ; we're done with this for now
-
- jsr GetPrefsFromDisk ; stuff to find prefs path and read it
-
- _AddNotifyProcGS NotifyProcParms
-
- rts
-
- OurBuffer dc.w 0 ; recvCount
- TargetID dc.w 0 ; ID of any IRs around
- OurVersion dc.w 0 ; Version for any IR already installed
-
- EndP
-
-
- EJECT
- *******************************************************************************
- *
- IRSaysIRHere PROCNAME
- *
- * Description: Simple procedures -- we just accept it to say we're here.
- * If we're in the middle of starting up, we do _not_ accept
- * this request.
- *
- *
- * Inputs: None. dataIn is ignored.
- *
- * Outputs: dataOut points to a buffer:
- * +000 recvCount
- * +002 IR user ID
- * +004 IR's version longword
- *
- * External Refs: None.
- *
- * Entry Points:
- WITH IRData
- *
- *******************************************************************************
-
- lda IRUserID
- bne @Accept
- stz <result ; denying the request
- clc
- bra @rts ; so I can't stand multiple exit paths
-
- @Accept ldy #4
- lda IRVersion
- sta [<dataOut],y
- iny
- iny
- lda IRVersion+2
- sta [<dataOut],y ; put our version in the output buffer.
-
- lda IRUserID ; again
- sec ; carry set makes the main request proc
- @rts rts ; return A at +002 in dataOut
-
- EndP
-
- EJECT
- *******************************************************************************
- *
- IRGetsToWork PROCNAME
- *
- * Description: Here it is, finally, the meat and potatoes of IR. This is
- * the request procedure that does what it is that IR does --
- * install things after boot.
- *
- *
- * Inputs: dataIn to the request proc is formatted as follows:
- *
- * word: flags (defined in E16.IR)
- * long: pointer to class one pathname of file to install
- * word: filetype
- * long: auxtype
- *
- * Outputs: dataOut is a pointer formatted as follows:
- *
- * word: recvCount (number of acceptors)
- * word: irError (any error code)
- * word: user ID assigned to installed file
- *
- * External Refs:
- with IRData
- import CheckFileAuxType
- import DoDrivers
- import DoInitsFEs
- import DoCDAs
- import DoNDAs
- import OpenNDAByUserID
- import UserIDToDAID
- import DoAlertWindow
- import AddIDToQueue
- *
- * Entry Points:
- *
- *******************************************************************************
-
- KillWithoutMercy equ Temp+2 ; temporary flag for power users
-
- stz <ThisInitID
- stz <MyDPageFlag ; note that we did not allocate memory
- stz <KillWithoutMercy
-
-
- ; First, check the environment and see if we can do our thing.
-
- lda >OS_KIND
- and #$00FF ; only low byte significant
- cmp #$0001 ; OS_KIND == 1 -> GS/OS is active
- bne @IRCantDoIt
- @GSOSHere lda >OS_BUSY
- bpl @WeCanGoOn
- @IRCantDoIt lda #irGSOSNotAvail
- brl ErrorOut
-
- ; Next, set the local prefs depending on the flag word
-
- @WeCanGoOn lda [<dataIn] ; get the flags
- sta <TempPrefs
- ror a ; put bit zero in the carry
- bcs @GotPrefs
- lda LocalPrefs
- sta <TempPrefs ; if not bit zero, use regular preferences
-
-
- ;*** See if the file is one that we can install, and set up our direct page parameters
-
- @GotPrefs lda #1
- trb <TempPrefs ; clear bit zero
-
- ldy #2
- lda [<dataIn],y
- sta <FilePointer
- iny
- iny
- lda [<dataIn],y
- sta <FilePointer+2
- iny
- iny
- lda [<dataIn],y ; filetype
- sta <FileType
- iny
- iny
- lda [<dataIn],y ; auxtype low word
- sta <auxtype
- iny
- iny
- lda [<dataIn],y ; auxtype high word
- sta <auxtype+2
-
- tay ; high word in Y
- ldx <auxtype
- lda <FileType ; filetype in A
- jsr CheckFileAuxType
- bcc @ItsAnIRFile
-
- lda #irNotIRFile
- brl ErrorOut
-
- ;
- ; Search to see if the Loader knows about the file and do what the flags say.
- ; First, we look to see if any duplicates exist by calling GetUserID2.
- ;
-
-
- @ItsAnIRFile sta <ThisInitID ; range at first
-
- @TryDuplicate pha
- pei <FilePointer+2
- pei <FilePointer
- _GetUserID2
- plx ; the existing user ID
- stx <Temp ; hold it for a minute
- bcc @CheckForNDA
- brl @MustInitialLoad ; not found, have to get it from disk
-
- ;
- ; Check to see here if this is an existing NDA we should just open.
- ;
-
- @CheckForNDA lda <Filetype
- cmp #NDAType
- bne @NotNDA ; if equal, it's an existing NDA
-
- lda <TempPrefs
- and #irCopyExistNDAs
- bne @NotNDA ; skip if the flag isn't set
-
- pha ; space for result
- _DeskStatus
- pla
- beq @NotNDA ; skip if Desk Manager not started
-
- lda <Temp ; the user ID
- jsr OpenNDAByUserID
- brl @CleanUp ; get out of here
-
- ;
- ; Here's where the irKillDuplicates flag comes into play. If the flag is set, we refuse
- ; to go anywhere unless the thing accepts the srqGoAway code. If the flag is clear,
- ; we'll install a duplicate if srqGoAway is not accepted. (We can't just _Restart, since
- ; Restart for an installed file just returns the existing entry point -- jumping to the
- ; entry point of GSBug even when it's running is not a winning proposition, for example.
- ;
- ; 2.0a4 -- if we're going to remove a DA, we also must remove it from the
- ; Desk Manager's lists.
- ;
-
- @NotNDA cmp #DriverType
- bne @ReadyToRemove
- lda #irDuplicateWontDie
- sta <Temp ; used as an error code later on
- stz <ThisInitID ; no user ID here
- brl @CleanUp ; GS/OS drivers can never be removed, and
- ; the OS will reject duplicate ones so I
- ; don't bother asking it to.
-
- ;
- ; Sit down -- this gets complicated.
- ;
- ; <deep breath>
- ;
- ; OK. If we're in the Finder, we can't just kill duplicates. We'd have
- ; to send them finderSaysGoodbye first, but we can't do that if we're
- ; responding to finderSaysOpenFailed or finderSaysBeforeOpen. So, if we
- ; are in the Finder, we add the temporary preferences and the user ID of
- ; the duplicate to a "Delayed Start" queue -- we'll install everything in
- ; that queue next time we hit finderSaysIdle. So, we check to see if we
- ; are in the Finder, and we check to see if it's safe to do our thing.
- ; If so, proceed. If not, add the preferences and the user ID to the
- ; DelayedStartQueue and accept the request with the error "irDelayedStart."
- ;
- ; 2.0f1 -- we should skip all duplicate efforts if irNoDuplicates is clear.
- ;
-
- @ReadyToRemove lda <TempPrefs
- and #irNoDuplicates
- bne @TestForFinder
- brl @MustInitialLoad
-
- @TestForFinder lda FSHDataIn
- ora FSHDataIn+2 ; are we really in Finder?
- beq @SendGoAway ; no, so don't send finderSaysGoodbye
-
- ; We're in the Finder, but is it safe?
-
- lda IdleGlobalFlag
- bne @SendGoodbye ; if this is non-zero, it's OK to proceed.
-
- ; Not safe -- add things to queue!
-
- lda <Temp ; user ID
- ldx #DelayedStartQueue
- jsr AddIDToQueue ; add first the user ID
- lda <TempPrefs
- ldx #DelayedStartQueue
- jsr AddIDToQueue ; and then the preferences!
-
- lda #irDelayedStart
- sta <Temp ; used as an error code later on
- stz <ThisInitID ; no user ID here
- brl @CleanUp ; have to accept request but do nothing
-
-
-
- @SendGoodbye pea finderSaysGoodbye
- pea sendToUserID ; don't stop after one in case they have
- ; multiple request procedures
- pea 0 ; high word of target
- pei <Temp ; user ID
- lda #0
- pha
- pha ; dataIn is nil
- pha
- pha ; dataOut is nil
- _SendRequest
- bcc @SendGoAway
- brl @WontGoAway ; don't try srqGoAway if can't say goodbye
-
- @SendGoAway pea srqGoAway ; request code
- pea sendToUserID ; how to send
- pea 0
- pei <Temp ; the user ID to send to
- lda #0
- pha
- pha ; dataIn should be zero
- pushlong #srqOutBuffer
- _SendRequest
- tax ; save for a minute
- lda <KillWithoutMercy
- bne @CanGoAway
- txa ; restore error code
- bcs @WontGoAway
- lda srqResultID
- beq @WontGoAway ; can't kill them if they return zero, either
-
- @CanGoAway lda #0
- pha
- pha ; no name string
- pei <Temp ; the user ID
- pha
- pha ; address == 0
- _AcceptRequests ; removes the request proc for this guy
-
- lda <Filetype
- cmp #CDAType
- beq @RemoveCDA
- cmp #NDAType
- beq @RemoveNDA
- bra @NotDA
-
- @RemoveCDA ldx #1 ; CDAs
- lda <Temp ; the User ID
- jsr UserIDToDAID ; returns DA handle low word in X, high in Y
- phy
- phx
- _RemoveCDA
- bra @NotDA
-
- @RemoveNDA ldx #0
- lda <Temp ; the user ID
- jsr UserIDToDAID
- phy
- phx
- _RemoveNDA
-
- @NotDA pha ; space for result
- pei <Temp
- lda srqFlags
- bpl @noZombie
- pea 1 ; any non-zero or non-$8000 value
- bra @DoUSD
- @noZombie pea 0
- @doUSD _UserShutDown
- pla
- bra @MustInitialLoad
-
- @WontGoAway lda <TempPrefs
- and #irKillDuplicates
- beq @MustInitialLoad
-
- ;
- ; Here's where we ask the user if we should install a new one even though
- ; they said don't.
- ;
-
- lda <TempPrefs
- and #irIgnoreProblems
- bne @NoReprieve
-
- ldx #irDuplicateWontDieAlert
- ldy #irDuplicateWontDieAlert>>16
- jsr DoAlertWindow
- cmp #1 ; did we get the "go ahead" button?
- bne @NoReprieve
- shortm
- lda >KEYMODREG ; get modifiers in 8-bit mode
- longm
- and #$0040 ; is the option key down?
- beq @NoReprieve ; if option key not down, it's an error
-
- ;
- ; If they pressed option, go ahead and kill it anyway. Power-user feature
- ; requested by Dave Lyons.
- ;
-
- inc <KillWithoutMercy ; temporary flag
-
- brl @SendGoAway ; so send a goodbye message
-
- @NoReprieve lda #irDuplicateWontDie ; if not, return an error <sigh>
- brl ErrorOut
-
- @MustInitialLoad
-
- ;
- ; Before installing a Finder extension, see if we're really in the Finder
- ; and give the user a chance to not do it if we're not.
- ;
-
- lda <FileType
- cmp #GenLoadType
- bne @ReallyInitialLoad
- lda <Auxtype
- and #FindExtAuxMask
- cmp #FindExtAuxType
- bne @ReallyInitialLoad ; only do this for Finder extensions
-
- lda FSHDataIn
- ora FSHDataIn+2
- bne @ReallyInitialLoad
-
- lda <TempPrefs
- and #irIgnoreProblems
- bne @ReallyInitialLoad
-
- ldx #irNoFinderAlert
- ldy #irNoFinderAlert>>16
- jsr DoAlertWindow
- cmp #1
- beq @ReallyInitialLoad ; should we do this anyway?
- lda #irNoFinder ; if not, return the "We're not in Finder" error
- brl ErrorOut
- ;
- ; Call InitialLoad2 to get the file into memory
- ; If there was no direct page segment, allocate a 4K segment
- ;
-
- @ReallyInitialLoad pha ; word space
- pha ; word space
- pha
- pha ; long space
- pha ; word space
- pei <ThisInitID ; user ID range
- pei <FilePointer+2
- pei <FilePointer ; pointer of pathname
- pea 1 ; don't use special memory
- pea 1 ; GS/OS string pathname
- _InitialLoad2
- tax ; save error code
- pullword <ThisInitID ; now the real ID, not just a range
- pulllong <StartAddress
- pullword <DPagePtr
- pullword <DPageSize
- bcc @CheckForDP
- txa ; restore error code
- stz <ThisInitID ; we didn't load anything!
- brl ErrorOut
-
- ; Get direct page space if none was included in the file
-
- @CheckForDP lda <DPageSize
- beq @GottaGetMem ; already allocated
- bra @TimeToDispatch
-
- @GottaGetMem pha
- pha ; space for result
- pushlong #4096 ; 4K
- pei <ThisInitID
- pushword #$C015 ; locked, fixed, no bank cross, page aligned, bank
- lda #0
- pha
- pha ; bank zero
- _NewHandle
- tax ; save error code
- pulllong <Temp
- bcc @GotMem
- txa ; restore error code
- brl ErrorOut
-
- @GotMem lda [<Temp]
- sta <DPagePtr
- lda #4096
- sta <DPageSize
- sta <MyDPageFlag
-
-
- ; Dispatch to subroutines based on the filetype of the thing to do.
-
- @TimeToDispatch lda <FileType
- ldx #@endDispTable-@DispTable-4
- @checkNextType cmp @DispTable,x ; is this the filetype?
- beq @dispatch ; yes, then call a routine
- dex ; no, then keep checking
- dex
- dex
- dex
- bpl @checkNextType ; keep scanning table
-
- ; This is as good a place as any to put the table
-
- @DispTable
- dc.w PermInitType,DoInitsFEs
- dc.w TempInitType,DoInitsFEs
- dc.w CDAType,DoCDAs
- dc.w NDAType,DoNDAs
- dc.w GenLoadType,DoInitsFEs
- dc.w DriverType,DoDrivers
- @endDispTable
-
- @Dispatch jsr (@DispTable+2,x) ; call the routine
-
- @PostDispatch sta <Temp ; temporarily keep the error code
-
- ;
- ; If we're being called from our own finderSaysIdle proc, our finderSaysHello
- ; procedure won't get a chance to add this to the NeedsHelloQueue. It doesn't
- ; really need to, anyway, because we can safely send this request as long
- ; as we're called from that procedure. So check the IdleGlobalFlag to see if
- ; that's the case and, if so, act on it.
- ;
-
- lda IdleGlobalFlag
- beq @OpenNDAMaybe
-
- pea finderSaysHello
- pea sendToUserID ; Finder doesn't stop after one
- pea $0000 ; high word of target == zero
- pei <ThisInitID ; low word of target == user ID
- pushlong FSHdataIn ; data in from finderSaysHello
- lda #0
- pha
- pha ; dataOut is nil
- _SendRequest
-
- ;
- ; Now, check again to see if this is an NDA -- if it is, and we're supposed to
- ; open it, open it.
- ;
-
- @OpenNDAMaybe lda <FileType
- cmp #NDAType
- bne @CleanUp
- lda <TempPrefs
- and #irDontOpenNDAs ; this bit is set if we _don't_ open NDAs
- bne @CleanUp
- lda <ThisInitID
- jsr OpenNDAByUserID
-
- ;
- ; We're done with everything by now, so let's dispose of our memory if we need to
- ;
-
- @CleanUp lda <MyDPageFlag
- bne @DisposeMem
- lda <Temp
- bra ErrorOut
-
- @DisposeMem lda #0
- pha
- pha ; space for result
- pha ; high word of address
- pei <DPagePtr ; low word of address
- _FindHandle
- _DisposeHandle
-
- lda <Temp ; restore the error code (if any)
-
- ;
- ; That's it! Set the error and user ID and return.
- ;
-
- ErrorOut pha ; save error
- lda <ThisInitID
- ldy #4
- sta [<dataOut],y
- pla
- sec ; so the request proc returns it
- rts
-
- EndP
-
- EJECT
- *******************************************************************************
- *
- DoDrivers PROCNAME
- *
- * Description: Installs a GS/OS driver based on parameters on direct
- * page.
- *
- *
- * Inputs: Direct page values all set concerning driver to install
- *
- * Outputs: Any errors in A.
- *
- * External Refs:
- with IRData
- *
- * Entry Points:
- *
- *******************************************************************************
-
-
- ; First, we allocate a handle with a long pointer to each DIB plus a long count
- ; of how many DIBs there are...
-
- lda <Auxtype ; auxtype low word in A
- and #$003F ; mask off all but count of DIBs
- inc a ; increase that by one word
- asl a
- asl a ; multiply by four
-
- pha
- pha ; space for result
- pea $0000
- pha ; size
- lda IRUserID ; IR's user ID
- pha
- pea $8000 ; the driver will be loaded fixed and
- ; making this handle fixed will make a
- ; hole in low memory. So it's just
- ; locked.
- lda #0
- pha
- pha ; any location
- _NewHandle ; get the handle
- plx
- ply
- bcc @GotDIBBlock
- brl @RealDoneDriver ; get out if error
-
- @GotDIBBlock stx <Temp
- sty <Temp+2
- ldy #2
- lda [Temp]
- sta <DIBPtr
- lda [Temp],y
- sta <DIBPtr+2 ; put the pointer into DIBPtr
-
- ; Now, walk the driver structure and build the DIB Ptr we have to feed to INSTALL_DRIVER
-
- @WalkDIBs lda #0
- sta [DIBPtr]
- ldy #2
- sta [DIBPtr],y
-
- lda [StartAddress]
- clc
- adc <StartAddress
- sta <TempAlso
- lda #0
- adc <StartAddress+2
- sta <TempAlso+2 ; TempAlso contains pointer to first DIB
-
- lda <Auxtype
- and #$003F ; get the count again
- sta <Temp
- lda #1
- sta <Temp+2
-
- ; the cardinal number of DIB we're about to do (Temp+2) is in A
-
- @CheckTheCount cmp <Temp
- beq @CountOK
- blt @CountOK
- bra @DoneBuilding
-
- @CountOK asl a
- asl a ; multiply by four
- tay
- lda <TempAlso
- sta [DIBPtr],y
- iny
- iny
- lda <TempAlso+2
- sta [DIBPtr],y
-
- ; now we make TempAlso point to the next DIB
-
- lda [TempAlso]
- tax
- ldy #2
- lda [TempAlso],y
- sta <TempAlso+2
- stx <TempAlso
-
- inc <Temp+2
- lda <Temp+2
- bra @CheckTheCount
-
- ; we have the DIBPtr, now we feed it to INSTALL_DRIVER
-
- @DoneBuilding lda <Temp
- sta [DIBPtr]
-
- ;
- ; We set warm_cold_flag so new drivers think this is a cold start and do the right
- ; thing for them.
- ;
-
- lda >warm_cold_flag
- sta <TempAlso
- and #$FFFE
- sta >warm_cold_flag ; tell drivers it's a cold startup
-
- shortm
- lda >$E0C068
- pha
- lda >$E0C08B
- lda >$E0C08B
- longmx
-
- ldx <DIBPtr
- ldy <DIBPtr+2
- jsl INSTALL_DRIVER ; INSTALL_DRIVER
- sta <Temp
-
- shortm
- lda >$E0C083
- lda >$E0C083
- pla
- sta >$E0C068
- longmx
-
- lda <Temp
- bne @DoneFlagDriver ; don't do it if error
-
- ;
- ; Now, to activate the driver we have to give the Device Manager a call, and not just
- ; any call, but one that causes drivers to be called. DInfo will work.
- ;
-
- _DInfoGS DInfoParms ; DInfo call to dev #1
-
- ; Hey, we're done!
-
-
- @DoneFlagDriver lda <TempAlso ; the old flag value
- sta >warm_cold_flag
-
- @DoneGotMem pha
- pha
- pei <DIBPtr+2
- pei <DIBPtr
- _FindHandle
- _DisposeHandle
-
- lda #0
- @RealDoneDriver rts
-
- EndP
-
- EJECT
- *******************************************************************************
- *
- DoCDAs PROCNAME
- *
- * Description: Installs CDAs given parameters on direct page.
- *
- *
- * Inputs: Direct page has all the necessary stuff.
- *
- * Outputs: Error code in A.
- *
- * External Refs:
- with IRData
- *
- * Entry Points:
- *
- *******************************************************************************
-
- pha
- pha ; space for result
- pei <StartAddress+2
- pei <StartAddress
- _FindHandle
- _InstallCDA
-
- ;
- ; Now, we can't necessarily call _DeskShutDown to breathe the gift of life into the
- ; CDA, so we find the shutdown pointer and call it die-reckly.
- ;
-
- lda [<StartAddress] ; length byte of name string
- and #$00FF ; mask it off
- clc
- adc #5 ; account for length byte and Entry pointer
- adc <StartAddress
- sta <Temp
- lda <StartAddress+2
- adc #0 ; is this really necessary?
- sta <Temp+2 ; now Temp points to the ShutDown pointer
-
- lda [<Temp]
- sta @JSLCDA+1
- ldy #1
- lda [<Temp],y
- sta @JSLCDA+2 ; self-modify the JSL
-
- lda #0
- tax
- tay
-
- @JSLCDA jsl $000000 ; call the shutdown routine
-
- ;
- ; Actually, that should do it. Let's get out of here.
- ;
-
- @ReturnFromCDA lda #0
- rts
-
- EndP
-
- EJECT
- *******************************************************************************
- *
- DoNDAs PROCNAME
- *
- * Description: Installs the NDA and breathes life into it.
- *
- *
- * Inputs: All the goodies on direct page.
- *
- * Outputs: Any errors in A.
- *
- * External Refs:
- with IRData
- IMPORT UserIDToDAID
- *
- * Entry Points:
- *
- *******************************************************************************
-
- pha
- pha ; space for result
- pei <StartAddress+2
- pei <StartAddress
- _FindHandle
- _InstallNDA
-
- ;
- ; Next, give this NDA a "DeskShutdown" call just like it was boot time. Since
- ; we can't actually shut down the Desk Manager (any running application like
- ; the Finder would be really annoyed), we send the DA an individual "shutdown"
- ; code with the new CallDeskAcc call.
- ;
-
- lda <ThisInitID
- ldx #0
- jsr UserIDToDAID
-
- pha ; space for result
- pea $0002 ; call the Init routine by reference number
- pea $0000 ; high word of reference == 0
- pha ; low word == NDA ID
- lda #0
- pha ; zero == shutdown call
- pha
- pha ; nothing in XY
- _CallDeskAcc
- pla ; don't care about this
-
- ;
- ; Test to see if we need to do the Apple menu futz -- we don't if the preferences
- ; say we don't, and we don't if the Desk Manager isn't active.
- ;
-
- lda <TempPrefs
- and #irDontOpenNDAs
- beq @TestForFutz
- brl @DoneNDA
-
- @TestForFutz pha
- _DeskStatus
- pla
- bne @TimeForFutz
- brl @DoneNDA
-
- ;
- ; It's time. First, send it a "startup" code, then do the futz to refix the Apple
- ; menu without leaving the application.
- ;
-
- @TimeForFutz lda <ThisInitID
- ldx #0
- jsr UserIDToDAID
-
- pha ; space for result
- pea $0002 ; call the Init routine by reference number
- pea $0000 ; high word of reference == 0
- pha ; low word == NDA ID
- pea $0001 ; one == startup call
- lda #0
- pha
- pha ; nothing in XY
- _CallDeskAcc
- ; pla ; don't care about this
-
- @DoTheFutz pha
- ; pha ; space for result
- _GetSysBar
- pulllong <TempAlso
-
- lda [<TempAlso]
- tax
- ldy #2
- lda [<TempAlso],y
- sta <TempAlso+2
- stx <TempAlso ; TempAlso points to menu bar record
-
- ldy #$28 ; offset to list of menu handles
- lda [<TempAlso],y
- sta <Temp
- iny
- iny
- lda [<TempAlso],y
- sta <Temp+2 ; Temp now has handle of first menu
-
- lda [<Temp]
- tax
- ldy #2
- lda [<Temp],y
- sta <Temp+2
- stx <Temp ; now Temp points to first menu
-
- lda [<Temp] ; that's the ID of the first menu
- sta <Temp ; there it is
-
- pha
- _GetNumNDAs
- pla
- dec a ; don't count the NDA we just installed!
- sta <Temp+2
-
- ;
- ; By the way, this also depends on the fact that all the NDAs have menu items
- ; that are numbered from 1 to GetNumNDAs.
- ;
-
- @FutzLoop pei <Temp+2
- _DeleteMItem
- dec <Temp+2
- bne @FutzLoop
-
- pei <Temp ; ID of the Apple menu
- _FixAppleMenu
-
- lda #0
- pha ; calculate width
- pha ; calculate height
- pei <Temp ; ID of the menu
- _CalcMenuSize
-
- ;
- ; That's it!
- ;
-
- @DoneNDA lda #0
- rts
-
- EndP
-
-
- EJECT
- *******************************************************************************
- *
- DoInitsFEs PROCNAME
- *
- * Description: Installs and executes permanent and temporary inits and
- * Finder Extensions. The variations between the three
- * are so minor that one subroutine can handle them all.
- *
- *
- * Inputs: File information on direct page.
- *
- * Outputs: Any errors in A.
- *
- * External Refs:
- with IRData
- IMPORT AddIDToQueue
- *
- * Entry Points:
- *
- *******************************************************************************
-
- ;
- ; We call these things with the user ID in A, zero in X/Y and the direct page and
- ; stack set up. FEs and permanent inits have a word on the stack above the RTL
- ; address -- if they change the low bit from zero to one, the thing is shut down
- ; on returning. We'll push a $0001 there for temporary inits so we can share
- ; the same code, more or less.
- ;
-
- tsc
- sta MyStack
- tdc
- sta MyDP ; save my stack and DP values
-
- lda <DPageSize
- dec a
- clc
- adc <DPagePtr
- tcs ; got new stack pointer
-
- ldx #0
- lda <FileType
- cmp #TempInitType
- bne @NotTempInit
- inx
- @NotTempInit phx ; value above RTL address on stack
-
- pei <ThisInitID
- ldx <StartAddress
- ldy <StartAddress+1
-
- lda <DPagePtr
- tcd ; new direct page in -- can't use DP anymore
-
- txa
- sta >@InitJSL+1
- tya
- sta >@InitJSL+2 ; self-modify the JSL to point to the right place
-
- pea $FFFF
- plb
- plb ; this sets the DBR to $FFFF, which is what
- ; GS/OS does and should help you find bugs faster.
-
- pla ; the user ID
- ldx #0
- txy ; zeros in X and Y, user ID in the accumulator
-
- @InitJSL jsl $000000 ; self-modified
-
- ;
- ; Here we are, back from the whatever it was we just called.
- ;
-
- plx ; get result of "do we shutdown"
- lda >MyStack
- tcs
- lda >MyDP
- tcd ; got my stack frame back now
-
- phk
- plb ; set the B register back for us
-
- txa ; result word from stack
- and #$0001
- beq @CheckForFE ; if no shutdown, see if this is a Finder Ext.
-
- lda #0
- pha ; space for result
- pei <ThisInitID
- pha ; flag of zero -- get rid of it
- _UserShutDown
- pla ; discard this
- bra @DoneInitFE
-
- @CheckForFE lda <Filetype
- cmp #GenLoadType ; is this a Finder Extension?
- bne @DoneInitFE
-
- ;
- ; If we're here, we might need to store the user ID of this so we can kill it later
- ;
-
- lda <TempPrefs
- and #irKillFinderExts
- beq @DoneInitFE
-
- lda <ThisInitID
- ldx #FinderExtQueue
- jsr AddIDToQueue
-
- @DoneInitFE lda #0
- rts
-
- EndP
-
- EJECT
- *******************************************************************************
- *
- IRSeesIdle PROCNAME
- *
- * Description: We get to here on finderSaysIdle. Here's where we have to
- * look through all the IDs we have queued up and send
- * finderSaysHello to each of them. We also dispatch all
- * the programs saved in the DelayedStartQueue; we can install
- * them now because Finder can now accept their calls in
- * response to finderSaysHello.
- *
- *
- * Inputs: None
- *
- * Outputs: None
- *
- * External Refs:
- with IRData
- IMPORT GetQueuePtr
- IMPORT GetQueueHandle
- IMPORT KillThisQueue
- *
- * Entry Points:
- *
- *******************************************************************************
-
- QueuePtr equ TempAlso
-
- ;
- ; Try to get out quickly if we have no things to dispatch
- ;
-
- ldx #NeedsHelloQueue+lockQueueHandle
- jsr GetQueueHandle
- lda <QueuePtr
- ora <QueuePtr+2
- bne @StuffToDo
- bra @CheckDelayedStart
-
- @StuffToDo lda [<QueuePtr]
- tax
- ldy #2
- lda [<QueuePtr],y
- sta <QueuePtr+2
- stx <QueuePtr ; faster than GetQueuePtr
-
- lda [<QueuePtr]
- inc a ; account for overhead words
- asl a ; double it
- tay
- sty <Temp+2
-
- @DispatchLoop pea finderSaysHello
- pea sendToUserID ; Finder doesn't stop after one
- pea $0000 ; high word of target == zero
- ldy <Temp+2 ; the index
- lda [<QueuePtr],y
- pha ; low word of target == user ID
- pushlong FSHdataIn ; data in from finderSaysHello
- lda #0
- pha
- pha ; dataOut is nil
- _SendRequest
-
- dec <Temp+2
- dec <Temp+2 ; bump the index
- lda #2 ; this index value means we're done
- cmp <Temp+2
- bne @DispatchLoop
-
- ;
- ; We don't unlock the handle because we're going to dispose of it anyway
- ;
-
- ldx #NeedsHelloQueue
- jsr KillThisQueue
-
- ;
- ; Now check to see if there's anything that needs a delayed start.
- ;
-
- @CheckDelayedStart NAME
- ldx #DelayedStartQueue+lockQueueHandle
- jsr GetQueueHandle
- lda <QueuePtr
- ora <QueuePtr+2
- bne @MoreStuffToDo
- brl @DoNothing
-
- @MoreStuffToDo lda [<QueuePtr]
- tax
- ldy #2
- lda [<QueuePtr],y
- sta <QueuePtr+2
- stx <QueuePtr ; faster than GetQueuePtr
-
- lda [<QueuePtr]
- inc a ; account for overhead words
- asl a ; double it
- tay
- sty <Temp+2
-
- ;
- ; Now, at this point, we point to a queue entry that contains the preferences
- ; for this install. The next (decremented) queue entry contains the user ID
- ; for the thing we're trying to install. Get the preferences first and
- ; deal with the file next.
- ;
- ; Y == INDEX ON ENTRY TO TOP OF LOOP!
- ;
-
-
- @DispatchLoop2 lda [<QueuePtr],y ; the preferences
- sta InputFlags ; keep this for a second
- dey
- dey
- sty <Temp+2 ; index now points to user ID
-
- pha
- pha ; space for result
- lda [<QueuePtr],y
- pha ; user ID
- pea $0001 ; always file #1
- _LGetPathname2
- pla
- sta GFIPathPtr
- sta InputPath
- pla
- sta GFIPathPtr+2 ; put this in our GetFileInfo block
- sta InputPath+2 ; and in our parameters to IR
-
- _GetFileInfoGS GFIParms ; file must exist
- bcs @NextItem ; OK, if an error, we won't install
-
- lda GFIFileType
- sta InputType
-
- lda GFIAuxType
- sta InputAuxType
- lda GFIAuxType+2
- sta InputAuxType+2
-
- inc IdleGlobalFlag ; tell IRGetsToWork it's OK to do this!
- pushword #askIRToInstall
- pushword #sendToName+stopAfterOne
- pushlong #IRString
- pushlong #InputFlags ; address of input buffer
- pushlong #OutputCount ; address of output buffer
- _SendRequest ; and let's do it again!
- stz IdleGlobalFlag ; clear this puppy fast!
-
- ;
- ; We can't do anything about errors, so we don't worry too much.
- ;
-
- @NextItem dec <Temp+2
- dec <Temp+2 ; bump the index
- ldy <Temp+2 ; keep this index in Y!
- lda #2 ; this index value means we're done
- cmp <Temp+2
- bne @DispatchLoop2
-
- ldx #DelayedStartQueue
- jsr KillThisQueue
-
- bra @TimeToLeave
-
- @DoNothing stz <result ; denying the request
-
- @TimeToLeave lda #0
- clc
- rts ; just to be nice.
-
- InputFlags dc.w 0
- InputPath dc.l 0
- InputType dc.w 0
- InputAuxType dc.l 0
-
- OutputCount dc.w 0
- OutputResult dc.w 0
- OutputID dc.w 0
-
- EndP
-
- EJECT
- *******************************************************************************
- *
- IRGoesAway PROCNAME
- *
- * Description: This is our response to srqGoAway -- return our user ID
- * after killing all the Finder Extensions we may have
- * lying around.
- *
- *
- * Inputs: None
- *
- * Outputs: None
- *
- * External Refs:
- with IRData
- IMPORT KillQueueEntries
- IMPORT GetQueueHandle
- IMPORT NotifyProcCode
- *
- * Entry Points:
- *
- *******************************************************************************
-
- QueuePtr equ TempAlso
-
- lda IRBusyFlag
- bne @CantLeave
-
- @CheckHelloQ ldx #NeedsHelloQueue
- jsr GetQueueHandle
- lda <QueuePtr
- ora <QueuePtr+2
- beq @GoingAway ; don't go away if people need hellos
-
- @CantLeave lda #0 ; accepting with user ID of zero
- bra @Exit
-
- @GoingAway lda #1 ; non-zero
- ldx #FinderExtQueue
- jsr KillQueueEntries
-
- lda PrefsPathPtr
- ora PrefsPathPtr+2
- beq @NoPathHandle
-
- pha
- pha ; space for _FindHandle result
- pushlong PrefsPathPtr
- _FindHandle
- _DisposeHandle ; get rid of our pathname handle
- stz PrefsPathPtr
- stz PrefsPathPtr+2
-
- ;
- ; Call our "Switch to P8" notify proc to close out all our resource stuff
- ;
-
- @NoPathHandle jsl NotifyProcCode
-
- _DelNotifyProcGS NotifyProcParms
-
- lda IRUserID
- @Exit ldy #2
- sta [<dataOut],y
- iny
- iny
- lda #0 ; not restartable from memory
- sta [<dataOut],y
-
- ;
- ; In fact, I think we _are_ restartable from memory, but I don't have the
- ; time to test this, and it's better to be safe than sorry.
- ;
-
- clc
- rts
-
- RemoveBuffer dc.w 0 ; recvCount
- dc.w 0 ; Finder result
-
- EndP
-
- EJECT
- *******************************************************************************
- *
- KillQueueEntries PROCNAME
- *
- * Description: Sends srqGoAway to all user IDs in a queue. A is non-
- * zero if we need to send them finderSaysGoodbye as well.
- *
- *
- * Inputs: A is non-zero if we send finderSaysGoodbye as well as
- * srqGoAway. X contains the queue number for the queue
- * to use.
- *
- * Outputs: None.
- *
- * External Refs:
- with IRData
- IMPORT GetQueuePtr
- IMPORT GetQueueHandle
- IMPORT KillThisQueue
- IMPORT AddIDToQueue
- *
- * Entry Points:
- *
- *******************************************************************************
-
- QueuePtr equ TempAlso
-
- pei <QueuePtr+2
- pei <QueuePtr ; save this
- sta <Temp ; keep this around for a while
- stx QueueNum
-
- txa
- ora #lockQueueHandle
- tax
- jsr GetQueueHandle ; returns handle in TempAlso
-
- lda <QueuePtr
- ora <QueuePtr+2
- bne @FEsToKill
- brl @NoFEs ; handle not locked if it's not a handle
-
- ;
- ; OK, if we have things to kill, we can take a bit more time about it
- ;
-
- @FEsToKill ldx QueueNum
- jsr GetQueuePtr ; get the whole thing this time
-
- lda [<QueuePtr]
- inc a ; account for overhead words
- asl a ; double it
- tay
- sty <Temp+2
- pea $FFFF ; marker word for stack stuff
-
- @KillItLoop lda <Temp
- beq @SendGoAway
-
- @SendGoodbye pea finderSaysGoodbye
- pea sendToUserID ; don't stop after one in case they have
- ; multiple request procedures
- pea 0
- ldy <Temp+2 ; the index
- lda [<QueuePtr],y
- pha ; user ID
- lda #0
- pha
- pha ; dataIn is nil
- pha
- pha ; dataOut is nil
- _SendRequest
-
- @SendGoAway stz srqOutBuffer
- stz srqFlags
- stz srqResultID
- pea srqGoAway
- pea sendToUserID+stopAfterOne
- pea 0000 ; high word of target (user ID)
- ldy <Temp+2 ; the index
- lda [<QueuePtr],y
- pha ; user ID
- lda #0
- pha
- pha ; dataIn is nil
- pushlong #srqOutBuffer ; dataOut pointer
- _SendRequest
-
- ;
- ; If the request wasn't accepted, or if the resulting ID is zero (2.0a4),
- ; we can't shut it down
- ;
-
- bcs @CantShutDown
- lda srqResultID
- beq @CantShutDown
-
- ldx #0
- phx
- phx ; name pointer == NIL
- lda srqResultID
- pha
- phx
- phx
- _AcceptRequests ; take this request proc away
-
- pha ; space for result
- lda srqResultID ; result ID still there
- pha ; user ID
- lda srqFlags
- and #$8000 ; other bits are reserved
- lsr a ; makes $8000 into "non-zero" for loader
- pha ; the flags
- _UserShutDown
- pla ; discard this
- bra @NextEntry
-
- @CantShutDown ldy <Temp+2
- lda [<QueuePtr],y ; the user ID
- pha ; save it on the stack
-
- @NextEntry dec <Temp+2
- dec <Temp+2 ; bump the index
- lda #2 ; this index value means we're done
- cmp <Temp+2
- beq @DoneLoop
- brl @KillItLoop
-
- @DoneLoop ldx QueueNum
- jsr KillThisQueue
-
- ;
- ; Okay, now we've tried to kill everything in the queue and we've pushed
- ; the user IDs of any items that wouldn't go away. If any such items exist,
- ; we need to recreate them in the queue for trying again later.
- ;
-
- @RecreateQ pla
- cmp #$FFFF ; is it our flag word?
- beq @NoFEs
- ldx QueueNum
- jsr AddIDToQueue
- bra @RecreateQ
-
- @NoFEs pulllong QueuePtr
- lda #0
- clc
- rts ; just to be nice.
-
- QueueNum dc.w 0 ; local storage
-
- EndP
-
- EJECT
- *******************************************************************************
- *
- GetPrefsFromDisk PROCNAME
- *
- * Description: Gets the preferences from the disk file into our data
- * area. Also sets up the pathname to the preferences file,
- * the parameter blocks, etc.
- *
- *
- * Inputs: None.
- *
- * Outputs: Error in A/carry.
- *
- * External Refs:
- with IRData
- IMPORT MakePrefsPath
- *
- * Entry Points: None.
- *
- *******************************************************************************
-
- ;
- ; First, set up the default preferences in both prefs locations so if we can't
- ; get the disk preferences, we have something valid.
- ;
-
- lda #irDefaultPrefs
- sta DiskPrefs
- sta LocalPrefs
-
- ;
- ; Next, construct the pathname to the preferences file.
- ;
-
- jsr MakePrefsPath ; this is gnarly and needs to be called more than
- ; once
- bcs PrefsError
-
- ;
- ; OK. Now, try to open the file and read the preferences.
- ;
-
- lda #readEnable
- sta OpenAccess
- _OpenGS OpenParms
- bcs PrefsError
-
- lda OpenRefnum
- sta RWrefnum
- sta CloseRefnum
- _ReadGS RWParms
-
- ;
- ; 2.0a4 -- remember to close the file, dummy
- ;
-
- php
- pha ; save error state
- _CloseGS CloseParms
- pla
- plp ; return error from Read, not Close
- bcs PrefsError
-
- lda DiskPrefs
- sta LocalPrefs
-
- ;
- ; That's it.
- ;
-
- lda #0
- clc
- PrefsError rts
-
- EndP
-
- EJECT
- *******************************************************************************
- *
- PutPrefsToDisk PROCNAME
- *
- * Description: Writes the preferences in DiskPrefs to disk.
- *
- *
- * Inputs: None
- *
- * Outputs: Error in A/carry
- *
- * External Refs:
- with IRData
- IMPORT MakePrefsPath
- *
- * Entry Points: None.
- *
- *******************************************************************************
-
- jsr MakePrefsPath ; make sure we have the right path
- bcs PutPrefsError
-
- @OpenFile lda #writeEnable
- sta OpenAccess
- _OpenGS OpenParms
- bcc @NowWrite
- cmp #$0046 ; is it file not found?
- sec ; because the cmp affects it
- bne PutPrefsError
-
- @CreateFile _CreateGS CreateParms
- bcc @OpenFile
- bcs PutPrefsError
-
- @NowWrite lda OpenRefnum
- sta RWrefnum
- sta CloseRefNum
- _WriteGS RWParms
-
- php ; now close the file regardless of error
- pha ; save error state
- _CloseGS CloseParms
- pla
- plp ; return write error, not close.
- bcs PutPrefsError
-
- lda DiskPrefs
- sta LocalPrefs
-
- ;
- ; That's it.
- ;
-
- lda #0
- clc
- PutPrefsError rts
-
- EndP
-
- EJECT
- *******************************************************************************
- *
- IRReturnsPreferences PROCNAME
- *
- * Description: Returns preferences in the third word of the buffer
- * pointed to by dataOut. If the low bit of dataIn is
- * set, we read the prefs from disk before returning them.
- *
- *
- * Inputs: low bit of dataIn set == read from disk
- *
- * Outputs: dataOut +004 == preferences
- * Error in A/carry
- *
- * External Refs:
- with IRData
- *
- * Entry Points:
- *
- *******************************************************************************
-
- lda <dataIn
- ror a
- bcc @justReturnPrefs
-
- jsr GetPrefsFromDisk
- bcs @PrefsError
-
- @justReturnPrefs lda LocalPrefs
- ldy #4
- sta [<dataOut],y
-
- lda #0
- sec
- @PrefsError rts
-
- EndP
-
- EJECT
- *******************************************************************************
- *
- IRSetsPreferences PROCNAME
- *
- * Description: Takes preferences in the low word of dataIn and sets them
- * in memory. If the low bit (irDoDiskPrefs) is set, they're
- * written to disk as well, if possible, but they're always
- * written to memory even if disk errors occur.
- *
- *
- * Inputs: New prefs in dataIn
- *
- * Outputs: Second word of dataOut == result code
- *
- * External Refs:
- with IRData
- *
- * Entry Points:
- *
- *******************************************************************************
-
- lda <dataIn
- and #$FFFE ; clear out bit zero first!
- sta LocalPrefs
- lda <dataIn
- ror a
- bcc @justSetPrefs
-
- asl a ; shift back and clear low bit at once
- sta DiskPrefs
- jsr PutPrefsToDisk
- bcs @PrefsError
-
- @justSetPrefs lda #0
- sec
- @PrefsError rts
-
- EndP
-
-
- EJECT
- *******************************************************************************
- *
- MakePrefsPath PROCNAME
- *
- * Description: Creates the pathname used for the preferences file and
- * propagates it throughout the parameter blocks. The order
- * used to create the path is as follows:
- *
- * 1) If this file is on AppleShare, preferences are in
- * the user folder.
- * 2) If this file is not on a network volume, prefs are
- * stored with this file.
- *
- * Inputs: Carry is set to force local path instead of AppleShare.
- * Carry set also forces a path rebuild.
- *
- * Outputs: None
- *
- * External Refs:
- with IRData
- *
- * Entry Points:
- *
- *******************************************************************************
-
- ;
- ; First see if we've already done this...
- ;
-
- @CheckPath lda PrefsPathPtr
- ora PrefsPathPtr+2
- beq @NoPath
- @WereDone brl GotPrefsPath
-
- @NoPath pha
- pha ; space for result
- lda IRUserID
- pha ; our ID
- pea $0001 ; file number always == 1
- _LGetPathname2
- tax
- pulllong <Temp
- txa ; preserve error code
-
- bcc @0
- brl PrefsPathError
-
- @0 lda <Temp
- sta GFIPathPtr
- lda <Temp+2
- sta GFIPathPtr+2 ; get ready for GetFileInfo
-
- _GetFileInfoGS GFIParms
- bcc @1
- brl PrefsPathError
-
- @1 lda OptionListFSID
- cmp #appleShareFSID ; is our file on AppleShare
- beq @DoUserPath
- brl @DoLocalPath
-
- ;
- ; If we get here, we need to get the user path from the AppleShare FST. The call
- ; is simple; we just set up the strange local variables like we were looking at
- ; a local pathname and use much of the same code. First, get the path.
- ;
-
- @DoUserPath _FSTSpecific UserPathParms
- bcs @DoLocalPath ; do this locally if data unavailable
-
- lda UserPathPtr
- sta <Temp
- lda UserPathPtr+2
- sta <Temp+2
-
- ; To put an index-like value in Y, get the length and add 2 to it.
-
- lda [<Temp]
- inc a
- inc a
- tay
-
- ; That's all the AppleShare-specific stuff; fall through to a common construction
- ; routine
-
- bra @Common
-
- ;
- ; Now, for a local pathname:
- ; Get the length of the pathname, add 2-1 to account for the length word, and start
- ; indexing backwards looking for a colon (:)
- ;
-
- @DoLocalPath lda [<Temp]
- inc a
- tay
- shortm ; 8-bit accumulator
-
- @ColonLoop lda [<Temp],y
- cmp #':'
- beq @FoundTheColon ; (no remarks about anatomy, please)
- dey
- bra @ColonLoop ; there has to be at least one colon
-
- @FoundTheColon longm
-
- ;
- ; OK, now we have the colon place. Now think carefully about this -- I got this wrong
- ; bunches of times. GSBug is your friend.
- ; Because of the length word at the beginning of the LGetPathname2 result, the _length_
- ; of the result MINUS THE FILENAME is two more than what's in Y. So, to get the length
- ; of the handle to allocate for the preferences path, we subtract two from Y, then add
- ; the length of the preferences file name and two bytes for the length buffer. That
- ; simplifies to adding the length of the preferences file to Y and we've got it.
-
-
- @Common phy ; save this for a second
- clc
- lda PrefsFileName
- and #$00FF
- adc 1,s ; add with saved index
- sta TempLength ; keep this for later
-
- pha
- pha ; space for result
- pea 0
- pha ; size
- pushword IRUserID
- pushword #$4008 ; fixed, no special memory
- lda #0
- pha
- pha
- _NewHandle
- pulllong <TempAlso
- pha ; save error code
- lda [<TempAlso]
- tax
- ldy #2
- lda [<TempAlso],y
- sta <TempAlso+2
- stx <TempAlso
- pla ; restore error code
- ply ; restore index into y
- bcc @2
- brl PrefsPathError ; thought I'd forgotten error checking, didn'cha?
-
- ;
- ; Now, TempAlso points to memory we want to move that amount of bytes to -- from [Temp]+2
- ; and ranging for index - 2, moved to [TempAlso] + 2.
- ;
-
- @2 phy ; save the index again
-
- clc
- lda <Temp
- adc #2
- tax
- lda <Temp+2
- adc #0
- pha
- phx ; source
-
- clc
- lda <TempAlso
- adc #2
- tax
- lda <TempAlso+2
- adc #0
- pha
- phx ; destination
-
- tya ; index
- dec a
- dec a
- pea $0000
- pha ; count
- _BlockMove
-
- ply ; restore the index
-
- ;
- ; Now (and I was told there'd be no math, <sigh>) add the index (which, remember, includes
- ; the length word) to <TempAlso to get the address of the place to move "IR.Preferences".
- ;
-
- tya
- clc
- adc <TempAlso
- sta <Temp ; we're done with LGetPathname2 now
- lda #0
- adc <TempAlso+2
- sta <Temp+2
-
- pushlong #PrefsFileName+1 ; don't forget to not move the length byte!
- pei <Temp+2
- pei <Temp
- lda PrefsFileName
- and #$00FF
- pea 0000
- pha ; count
- _BlockMove
-
- ;
- ; Now, fix the length word and everything is OK. Subtract 2 because it includes
- ; the length word.
-
- lda TempLength
- dec a
- dec a
- sta [<TempAlso]
-
- ;
- ; Finally, Temp contains the address of our GS/OS pathname to the preferences file. Move
- ; it into permanent storage and propagate it throughout the parameter blocks.
- ;
-
- lda <TempAlso
- sta PrefsPathPtr
- sta CreatePath
- sta OpenPath
- lda <TempAlso+2
- sta PrefsPathPtr+2
- sta CreatePath+2
- sta OpenPath+2
-
- GotPrefsPath lda #0
- clc
- PrefsPathError rts
-
- TempLength dc.w 0 ; temporary length storage
- LocalFlag dc.w 0 ; flag to see if this is forced to local
-
- EndP
-
- EJECT
- *******************************************************************************
- *
- CheckFileAuxType PROCNAME
- *
- * Description: Takes a filetype in A and auxtype in X (low) and Y (high)
- * and sees if IR can install this. Returns carry clear if
- * we can and carry set if we can't. Also returns user ID
- * range for this thing we're trying to load.
- *
- *
- * Inputs: Filetype in A, auxtype in X (low) and Y (high)
- *
- * Outputs: Carry clear if IR does anything. User ID to pass to
- * InitialLoad2 in A, or zero if carry is set.
- *
- * External Refs:
- WITH IRData
- * uses FileType and AuxType on direct page
- *
- * Entry Points:
- *
- *******************************************************************************
-
- ;
- ; First, see if the auxtype high word is zero -- if not, we don't do this
- ; type.
- ;
-
- cpy #0
- bne @NotOurType
-
- ;
- ; OK, so store the types on direct page and begin checking the table.
- ;
-
- sta Filetype
- stx Auxtype
-
-
- ldx #0 ; initialize this index
- ldy FTTableCount ; this one too
-
- @FileTypeLoop lda fileTypeTable,x ; the filetype
- cmp <FileType
- bne @NextTypeEntry
-
- lda <Auxtype
- and fileTypeTable+2,x ; the auxtype mask
- cmp fileTypeTable+4,x ; the desired auxtype
- beq @GotIt ; we found our type
-
- @NextTypeEntry dey
- beq @NotOurType ; not ours
- clc
- txa
- adc #sizeOfFTEntry
- tax ; next entry
- bra @FileTypeLoop
-
- @GotIt lda fileTypeTable+6,x ; the user ID range
- clc
- rts
-
- @NotOurType lda #0
- sec
- rts
-
- EndP
-
- EJECT
- *******************************************************************************
- *
- IRDoesPreferences PROCNAME
- *
- * Description: Test/do the IR preferences dialog box.
- *
- *
- * Inputs: None
- *
- * Outputs: None
- *
- * External Refs:
- with IRData
- import GetPrefsFromControls
- import SetControlsFromPrefs
- import SetPrefs
- import GiveMeMyFork
- *
- * Entry Points:
- *
- *******************************************************************************
-
- RectPtr equ Temp
- PrefsPtr equ TempAlso
- AlertPtr equ DIBPtr ; this should be safe in here
-
- ;
- ; Zeroth (before first but written later), do nothing if the Window
- ; Manager isn't active.
- ;
-
- pea $0000
- _WindStatus
- pla
- bne @First
- brl Out ; do nothing if no Window Manager
-
-
- ;
- ; First, get our resource file ready and get the TwoRects resource.
- ;
-
- @First jsr GiveMeMyFork
-
- pha
- pha ; space for result
- pushword #rTwoRects ; type
- pushlong #WindowRects ; ID
- _LoadResource
- pulllong <RectPtr
- bcc @NoError0
- brl Out ; no error reporting, but get out of here
-
- @NoError0 lda [<RectPtr]
- tax
- ldy #2
- lda [<RectPtr],y
- sta <RectPtr+2
- stx <RectPtr ; RectPtr now points to rectangles
-
- ;
- ; Now, get our AlertString resource and window resource for adjusting their
- ; rectangles
- ;
-
- pha
- pha ; space for result
- pushword #rAlertString
- pushlong #irAboutAlert
- _LoadResource
- pulllong <AlertPtr
- bcc @NoError1
- brl Out ; no error reporting, but get out of here
-
- @NoError1 lda [<AlertPtr]
- tax
- ldy #2
- lda [<AlertPtr],y
- sta <AlertPtr+2
- inx
- stx <AlertPtr ; AlertPtr now points to alert rectangle
- ; we can do that because the alert resource
- ; is marked noBankCross.
-
- pha
- pha ; space for result
- pushword #rWindParam1
- pushlong #Preferences_Window
- _LoadResource
- pulllong <PrefsPtr
- bcc @NoError2
- brl Out ; no error reporting, but get out of here
-
- @NoError2 lda [<PrefsPtr]
- tax
- ldy #2
- lda [<PrefsPtr],y
- sta <PrefsPtr+2
- stx <PrefsPtr ; PrefsPtr now points to preferences window
- clc
- lda #owPosition
- adc <PrefsPtr
- sta <PrefsPtr ; PrefsPtr now points to window rectangle
- ; we can do that because the alert resource
- ; is marked noBankCross.
-
- ;
- ; Then adjust the rectangles for whatever mode we're in
- ;
-
- @RectFutz pha
- _GetMasterSCB
- pla
- and #$0080 ; mask out all but the 320/640 bit
- beq @MoveRect ; <RectPtr already points to 320 rectangle
- @Do640 lda #8
- clc
- adc <RectPtr
- sta <RectPtr
- lda #0
- adc <RectPtr+2
- sta <RectPtr+2 ; RectPtr := RectPtr + 8 --> points to 640 rect
- @MoveRect ldy #6
- @MoveRectLoop lda [RectPtr],y
- sta [PrefsPtr],y
- sta [AlertPtr],y
- dey
- dey
- bpl @MoveRectLoop
-
- ;
- ; Then, release the rectangle resource and create the window
- ;
-
- pushword #$FFFF ; negative == kill it now
- pushword #rTwoRects
- pushlong #WindowRects
- _ReleaseResource
-
- lda #0
- pha
- pha ; space for result
- pha
- pha ; no replacement title
- pha
- pha ; no refcon
- pha
- pha ; no replacement content draw routine
- pha
- pha ; standard defproc
- pushword #2 ; reference is by resource
-
- ;
- ; By the way, we can do that (^^^) because as long as the resource is loaded and
- ; non-purgeable, the Resource Manager will return the previous handle. We
- ; must _not_ mark it as "changed" or the Resource Manager will try to
- ; write it to disk, and that would be Bad.
- ;
-
- pushlong #Preferences_Window ; window reference
- pea $800E ; template like rWindParam1
- _NewWindow2
- pulllong <PrefsWindPtr
-
- @MakeCtlsRight lda LocalPrefs
- jsr SetControlsFromPrefs
-
- ;
- ; Before showing the window, change the preferences control to point to
- ; our version string (left over from IRStartsUp).
- ;
-
- pha
- pha ; space for result
- pei <PrefsWindPtr+2
- pei <PrefsWindPtr
- pushlong #VersionID
- _GetCtlHandleFromID
- pulllong <Temp ; save for a bit
-
- pushlong #IRBootVersion+1
- pei <Temp+2
- pei <Temp
- _SetCtlTitle ; no length word
-
- pushword VersionLength
- pei <Temp+2
- pei <Temp
- _SetCtlValue ; value == length of static text
-
- pei <PrefsWindPtr+2
- pei <PrefsWindPtr
- _ShowWindow
-
- @ModalWindLoop lda #0
- pha
- pha ; space for result
- pushlong #MyTaskRec ; task record
- lda #0
- pha
- pha ; standard update proc
- pushlong #$80000000 ; standard event hook, leaves $0000 in A
- pha
- pha ; standard beep procedure
- pea %1000000000000000 ; flags
- _DoModalWindow
- pulllong <Temp ; the ID of the control hit
-
- ;
- ; See if we hit a dismissing control or the version number. We only test the low
- ; word of each ID because we restrict control IDs to less than $10000.
- ;
-
- lda <Temp
- cmp #AcceptID
- bne @notAccept
- @isAccept jsr GetPrefsFromControls
- sta LocalPrefs
- jsr SetPrefs
- brl ClosePrefsWindow
-
- @notAccept ;lda <Temp
- cmp #CancelID
- bne @notCancel
- @isCancel brl ClosePrefsWindow
-
- @notCancel ;lda <Temp
- cmp #SaveID
- bne @notSave
- @isSave jsr GetPrefsFromControls
- sta LocalPrefs
- ora #IrDoDiskPrefs
- jsr SetPrefs
- brl ClosePrefsWindow
-
- @notSave ;lda <Temp
- cmp #VersionID
- bne @notVersion
- @isVersion lda #0
- pha ; space for result
- pea $02AC ; string is resource, no sub strings,
- ; use new button placement, no sound,
- ; ignore icon rect when centering text,
- ; use icon resource instead of inline icon,
- ; release resource to purge level 3 instead
- ; of disposing it.
- pha
- pha ; no substitution array
- pushlong #irAboutAlert ; Reference to alert string
- _AlertWindow
- pla
-
- @notVersion brl @ModalWindLoop ; do it over again
-
- ClosePrefsWindow pei <PrefsWindPtr+2
- pei <PrefsWindPtr
- _CloseWindow
-
- ;
- ; Since the AlertString and window resources are locked, we need to manually release
- ; them to get them disposed.
- ;
-
- Out pushword #$FFFF
- pushword #rAlertString
- pushlong #irAboutAlert
- _ReleaseResource
-
- pushword #$FFFF
- pushword #rWindParam1
- pushlong #Preferences_Window
- _ReleaseResource
-
- lda #0
- clc
- rts
-
- LocalPrefs dc.w irDefaultPrefs
- EndP
-
- EJECT
- *******************************************************************************
- *
- SetPrefs PROCNAME
- *
- * Description: I have a request procedure to set the preferences, but I
- * need to call a regular subroutine. So this is glue that
- * takes preferences in A and calls IRSetsPreferences.
- * This glue is not reentrant.
- *
- *
- * Inputs: Preferences in A.
- *
- * Outputs: Errors in A/carry.
- *
- * External Refs:
- with IRData
- *
- * Entry Points: None.
- *
- *******************************************************************************
-
- tax ; save preferences in X
- pushword #askIRSetPrefs
- pushword #SendToName+stopAfterOne
- pushlong #IRString
- pea 0000 ; high word
- phx ; preferences
- pushlong #PrefsDataOut
- _SendRequest
-
- lda PrefsResult
- cmp #1
- rts
-
- PrefsDataOut dc.w 0 ; recvCount
- PrefsResult dc.w 0
-
- EndP
-
- EJECT
- *******************************************************************************
- *
- GetPrefsFromControls PROCNAME
- *
- * Description: Takes the controls in the prefs window and returns an IR
- * preferences word with their contents, as we use them.
- *
- *
- * Inputs: PrefsWindPtr == pointer to the preferences window
- *
- * Outputs: Prefs word in accumulator
- *
- * External Refs:
- import ValueFromID
- *
- * Entry Points:
- *
- *******************************************************************************
-
- stz BuildPrefs ; zero out our building prefs word
-
- ;
- ; Set the irNoDuplicates bit if the "Always kill old file" radio button is selected
- ;
- ldy #AlwaysKillOldID
- ldx #AlwaysKillOldID>>16
- jsr ValueFromID
- beq @DuplicatesOK
- lda #irNoDuplicates+irKillDuplicates
- tsb BuildPrefs
- bra @DoneDuplicates
-
- @DuplicatesOK ldy #TryKillOldID
- ldx #TryKillOldID>>16
- jsr ValueFromID
- beq @DoneDuplicates ; taken if "always install new" is chosen
- lda #irNoDuplicates
- tsb BuildPrefs
-
- @DoneDuplicates ; the word is already zeroed.
-
- ;
- ; Set the irDontOpenNDAs bit if the "Open new NDAs" box is unchecked.
- ;
-
- ldy #OpenNewNDAID
- ldx #OpenNewNDAID>>16
- jsr ValueFromID
- bne @GotNDAs
- lda #irDontOpenNDAs
- tsb BuildPrefs
-
- @GotNDAs
-
- ;
- ; Set the irKillFinderExts bit if the "Install permanently" check box is NOT checked.
- ;
-
- ldy #FinderExtID
- ldx #FinderExtID>>16
- jsr ValueFromID
- bne @NoKillFEs
- lda #irKillFinderExts
- tsb BuildPrefs
-
- @NoKillFEs
-
- ;
- ; Set the irCopyExistNDAs bit if the "Open NDAs" check box is clear.
- ;
-
- ldy #CopyExistNDAsID
- ldx #CopyExistNDAsID>>16
- jsr ValueFromID
- bne @noOpenNDAs
- lda #irCopyExistNDAs
- tsb BuildPrefs
-
- @noOpenNDAs
-
- ;
- ; Set the irWaitOpenFailed bit if the "Give others..." check box is set.
- ;
-
- ldy #DoBeforeOpenID
- ldx #DoBeforeOpenID>>16
- jsr ValueFromID
- beq @noWaitOpenFailed ; don't set the bit if the box was empty
- lda #irWaitOpenFailed
- tsb BuildPrefs
-
- ;
- ; Set the irIgnoreProblems bit if "Alert me ..." check box is clear.
- ;
-
- @noWaitOpenFailed ldy #DoAlertsID
- ldx #DoAlertsID>>16
- jsr ValueFromID
- bne @dontIgnoreProblems
- lda #irIgnoreProblems
- tsb BuildPrefs
-
- @dontIgnoreProblems lda BuildPrefs
- rts ; that's it!
-
- BuildPrefs dc.w 0 ; for temporary storage
-
- EndP
-
- EJECT
- *******************************************************************************
- *
- SetControlsFromPrefs PROCNAME
- *
- * Description: Takes a prefs word in A and initializes the controls in
- * the prefs window to the indicated states.
- *
- *
- * Inputs: Prefs word in A, PrefsWindPtr == pointer to prefs window
- *
- * Outputs: None
- *
- * External Refs:
- import SetValueFromID
- *
- * Entry Points:
- *
- *******************************************************************************
-
- sta BuildPrefs ; keep this
-
- ;
- ; Select the "Install a new copy" radio button if irNoDuplicates is clear
- ;
-
- and #irNoDuplicates
- bne @MoreDuplicates
- lda #1
- ldy #InstallNewID
- ldx #InstallNewID>>16
- jsr SetValueFromID
- bra @DoneDuplicates
-
- ;
- ; So, irNoDuplicates is set -- now set "Always remove old one" if irKillDuplicates is set.
- ;
-
- @MoreDuplicates lda BuildPrefs
- and #irKillDuplicates
- beq @SetTryButton
- lda #1
- ldy #AlwaysKillOldID
- ldx #AlwaysKillOldID>>16
- jsr SetValueFromID
- bra @DoneDuplicates
-
- @SetTryButton lda #1
- ldy #TryKillOldID
- ldx #TryKillOldID>>16
- jsr SetValueFromID
-
- @DoneDuplicates
-
- ;
- ; Now for the checkboxes
- ; Set the "Open new NDAs" box if irDontOpenNDAs is clear.
- ;
-
- lda BuildPrefs
- and #irDontOpenNDAs
- eor #irDontOpenNDAs
- ;
- ; That's a nifty trick, by the way -- if the bit was set, the eor makes the whole word
- ; zero, which will be an unchecked value. If the bit was clear, the eor makes it set,
- ; which makes A hold a non-zero value that will check the check box.
- ;
- ldy #OpenNewNDAID
- ldx #OpenNewNDAID>>16
- jsr SetValueFromID
-
- ;
- ; Next, set the "Install FEs permanently" if irKillFinderExts is clear
- ;
-
- lda BuildPrefs
- and #irKillFinderExts
- eor #irKillFinderExts ; see above, same trick
- ldy #FinderExtID
- ldx #FinderExtID>>16
- jsr SetValueFromID
-
- ;
- ; Next, check the "Open existing NDAs" box if irCopyExistNDAs is clear.
- ;
-
- lda BuildPrefs
- and #irCopyExistNDAs
- eor #irCopyExistNDAs
- ldy #CopyExistNDAsID
- ldx #CopyExistNDAsID>>16
- jsr SetValueFromID
-
- ;
- ; Check the "Alert me..." box if irIgnoreProblems is clear.
- ;
-
- lda BuildPrefs
- and #irIgnoreProblems
- eor #irIgnoreProblems
- ldy #DoAlertsID
- ldx #DoAlertsID>>16
- jsr SetValueFromID
- ;
- ; And check the "Give others..." check box if irWaitOpenFailed is set.
- ;
-
- lda BuildPrefs
- and #irWaitOpenFailed
- ldy #DoBeforeOpenID
- ldx #DoBeforeOpenID>>16
- jsr SetValueFromID
-
- rts ; that's it!
-
- BuildPrefs dc.w 0 ; temporary storage
-
- EndP
-
- EJECT
- *******************************************************************************
- *
- ValueFromID PROCNAME
- *
- * Description: Gets the control value from a control ID.
- *
- *
- * Inputs: Control ID (high/low) in X/Y
- *
- * Outputs: Control value in the accumulator
- *
- * External Refs:
- *
- * Entry Points:
- *
- *******************************************************************************
-
- pha ; space for resulting control value
- pha
- pha ; space for control handle
- pei <PrefsWindPtr+2
- pei <PrefsWindPtr ; window pointer
- phx ; high word of ID
- phy ; low word of ID
- _GetCtlHandleFromID
- _GetCtlValue
- pla ; got the control value in A
- rts
-
- EndP
-
- EJECT
- *******************************************************************************
- *
- SetValueFromID PROCNAME
- *
- * Description: Takes a control value in A and a control ID in X/Y
- * (high/low) and sets that control's value.
- *
- *
- * Inputs: Control value in A, ID in X/Y
- *
- * Outputs: None
- *
- * External Refs:
- *
- * Entry Points:
- *
- *******************************************************************************
-
- pha ; save the value
- pha
- pha ; space for control handle
- pei <PrefsWindPtr+2
- pei <PrefsWindPtr
- phx
- phy ; the control ID
- _GetCtlHandleFromID
- _SetCtlValue
- rts
-
- EndP
-
- EJECT
- *******************************************************************************
- *
- AddIDToQueue PROCNAME
- *
- * Description: Our "queues" are a word count of how many user IDs are in
- * them, a word count of how many user IDs the current
- * handle size will hold, and a lot of user IDs. If the
- * handle is zero, there is no handle and we allocate a
- * new one. If the handle will hold more user IDs, we just
- * add the new one. If it won't, we grow it by a fixed
- * amount and then add the new one.
- *
- *
- * Inputs: User ID to add in A, Queue number in X.
- *
- * Outputs: None. No errors because if we can't grow a handle
- * by a measly 40 bytes or so, the system's already in
- * serious trouble.
- *
- * External Refs:
- with IRData
- IMPORT GetQueuePtr
- *
- * Entry Points:
- *
- *******************************************************************************
-
- ;
- ; A couple of private, helpfully documenting equates
- ;
-
- UserID equ Temp
- QueueNum equ Temp+2
- QueuePtr equ TempAlso
-
- tay ; save this for now
-
- pushlong Temp
- pushlong TempAlso ; save both these so we can use them
-
- sty <UserID
- stx <QueueNum
-
- jsr GetQueuePtr ; set up the pointer to this Queue
-
- ;
- ; Now, see if we can fit one more user ID into this Queue.
- ;
-
- ldy #2
- lda [<QueuePtr],y ; how many entries can this hold?
- sec
- sbc [<QueuePtr]
- bne @ItWillFit
-
- lda [QueuePtr],y ; entries this one can hold
- asl a ; each entry is two bytes
- clc
- adc #4 ; now A contains the size of this handle
- adc #startIDCount
- pea 0
- pha ; size
- pha
- pha ; space for result
- pei <QueuePtr+2
- pei <QueuePtr
- _FindHandle
- _SetHandleSize
-
- ldx <QueueNum
- jsr GetQueuePtr ; redereference and start over
-
- clc
- lda [<QueuePtr]
- adc #startIDCount
- sta [<QueuePtr] ; add count of new ID capability to queue
-
- ;
- ; At this point, QueuePtr contains a pointer to a queue that will definitely hold
- ; the user ID we want to add to it.
- ;
-
- @ItWillFit lda [<QueuePtr] ; how many entries are here?
-
- ;
- ; Since the counts are one-based, we have to increment the entry count by
- ; two so that when we double it, it includes the four bytes of overhead at the
- ; beginning.
- ;
-
- inc a
- inc a
- asl a ; double it
- tay
- lda <UserID
- sta [<QueuePtr],y
- lda [<QueuePtr]
- inc a
- sta [<QueuePtr]
-
- pulllong <TempAlso
- pulllong <Temp
-
- rts
-
- EndP
-
- EJECT
- *******************************************************************************
- *
- GetQueuePtr PROCNAME
- *
- * Description: GetQueuePtr takes a queue number in X and returns the
- * pointer to that queue in TempAlso.
- *
- * Inputs: Queue number in X.
- *
- * Outputs: Queue pointer in QueuePtr (TempAlso)
- *
- * External Refs:
- with IRData
- *
- * Entry Points:
- *
- *******************************************************************************
-
- QueuePtr equ TempAlso
-
- txa
- asl a
- asl a ; multiply by four for indexing
- tay
-
- lda QueueTable,y
- ora QueueTable+2,y
- bne @GotHandle
-
- @NeedHandle phy ; save the index
- pha
- pha ; space for result
- pushlong #startIDCount*2+4
- pushword IRUserID
- lda #0
- pha ; unlocked, totally open
- pha
- pha ; in any bank, etc.
- _NewHandle
- lda 5,s ; the saved index
- tay
- pla ; low word of handle
- sta QueueTable,y ; into the table
- tax
- pla
- sta QueueTable+2,y ; the low word of the handle
- sta <QueuePtr+2
- stx <QueuePtr
- ply ; balance the stack
-
- lda [<QueuePtr]
- tax
- ldy #2
- lda [<QueuePtr],y
- sta <QueuePtr+2
- stx <QueuePtr ; now QueuePtr points to the queue
-
- ldy #2
- lda #startIDCount
- sta [<QueuePtr],y ; how many this handle can hold
- lda #0
- sta [<QueuePtr] ; holds none right now
-
- bra @GotQueuePtr
-
- @GotHandle lda QueueTable,y
- tax
- lda QueueTable+2,y
- sta <QueuePtr+2
- stx <QueuePtr
-
- lda [<QueuePtr]
- tax
- ldy #2
- lda [<QueuePtr],y
- sta <QueuePtr+2
- stx <QueuePtr ; now QueuePtr points to the queue
-
- @GotQueuePtr rts
-
- EndP
-
- EJECT
- *******************************************************************************
- *
- GetQueueHandle PROCNAME
- *
- * Description: GetQueueHandle takes a queue number in X and returns the
- * handle to that queue in TempAlso. It does _NOT_ allocate
- * a new handle if one for that queue does not exist.
- *
- * If the high bit of X is set, the queue handle is locked
- * before it's returned.
- *
- * Inputs: Queue number in X.
- *
- * Outputs: Queue handle in QueuePtr (TempAlso)
- *
- * External Refs:
- with IRData
- *
- * Entry Points:
- *
- *******************************************************************************
-
- QueuePtr equ TempAlso
-
- phx ; save this
-
- txa
- asl a
- asl a ; multiply by four for indexing
- tay
-
-
- @ItsHandle lda QueueTable,y ; low word of handle for the queue
- tax
- lda QueueTable+2,y ; high word of handle
- sta <QueuePtr+2
- stx <QueuePtr
-
- pla ; the queue number
- bpl @Done ; if high bit clear, we're done
-
- lda <QueuePtr
- ora <QueuePtr+2
- beq @Done ; we're done if it's NIL, also
-
- ldy #4
- lda [<QueuePtr],y
- ora #$8000 ; set the locked bit
- sta [<QueuePtr],y
-
- @Done lda #0
- clc
- rts
-
- EJECT
- *******************************************************************************
- *
- KillThisQueue PROCNAME
- *
- * Description: Kills the handle for the queue number in X and stores
- * zeroes in the queue table for that queue's handle.
- *
- *
- * Inputs: Queue number in X.
- *
- * Outputs: None
- *
- * External Refs:
- with IRData
- *
- * Entry Points:
- *
- *******************************************************************************
-
- QueuePtr equ TempAlso
-
- pei <QueuePtr+2
- pei <QueuePtr ; save these real quick
-
- txa
- asl a
- asl a ; multiply by four for indexing
- tax
-
- @ItsHandle phx ; I need this shortly
- lda QueueTable,x ; low word of handle for the queue
- tay
- lda QueueTable+2,x ; high word of handle
- pha
- phy ; handle on stack
- _DisposeHandle ; get rid of it
- plx ; get this index back
-
- stz QueueTable,x
- stz QueueTable+2,x
-
- pulllong <QueuePtr ; restore this
-
- lda #0
- clc
- rts
-
-
- EJECT
- *******************************************************************************
- *
- OpenNDAByUserID PROCNAME
- *
- * Description: Takes a user ID in A and opens the NDA window for that
- * user ID. If the window is already open, it selects it
- * instead.
- *
- *
- * Inputs: User ID in A.
- *
- * Outputs: None. Assumes this is an NDA ID; takes no action if not.
- *
- * External Refs:
- *
- * Entry Points:
- ENTRY UserIDToDAID
- *
- *******************************************************************************
-
- ldx #0 ; we want NDA ID's
- jsr UserIDToDAID
- sta DANum ; redundant, but cleaner
-
- ;
- ; We could check to see if the NDA is already open here and call _SelectWindow,
- ; but (surprise!) OpenNDA does that for us! So if you're one of those people who
- ; based your NDA on Guillermo's original sample that returns an existing window
- ; pointer if the NDA is already open, you've got dead code in there -- your open
- ; routine isn't called if your NDA is already open. Never has been. It is on
- ; the Macintosh, though.
- ;
- ; 2.0a4 -- added InitCursor so the cursor is an arrow for the NDA's benefit.
- ;
-
- _InitCursor ; nice and polite-like
-
- pha ; space for result
- pushword DANum ; the ID of our NDA
- _OpenNDA
- pla ; discard the reference number
-
- lda #0
- clc
- rts
-
- *******************************************************************************
- *
- * UserIDToDAID takes a user ID in A and CDA = 1/NDA = 0 in X.
- * It returns the DA's ID in A (for NDAs) or the DA's handle in X/Y (CDAs)
- *
- *******************************************************************************
-
- UserIDToDAID name
- sta TheID ; keep this for reference
- txa
- clc
- ror a
- ror a ; now old bit 0 == new bit 15
- sta CDANDAFlag
-
- lda #1
- sta DANum ; starting count for our DA loop
-
- @DAInfoLoop pushword CDANDAFlag ; NDAs are always referenced by index
- pushword #0
- pushword DANum
- pushword #38 ; always 38 bytes long
- pushlong #DAInfoBuffer
- _GetDeskAccInfo
-
- @NoError lda CDANDAFlag
- bmi @CheckCDA
-
- @CheckNDA lda NDAUserID
- @CheckID cmp TheID ; is this what we're after
- beq @ThisIsIt
- inc DANum
- bra @DAInfoLoop
-
- @CheckCDA lda #0
- pha ; space for result
- pha ; don't change ID
- pushlong CDAHandle
- _SetHandleID ; no change, returns old ID
- pla
- bra @CheckID
-
- @ThisIsIt lda CDANDAFlag
- bmi @FinishCDA
-
- @FinishNDA lda DANum
- ldx NDAHandle
- ldy NDAHandle+2
- rts
-
- @FinishCDA lda #0
- ldx CDAHandle
- ldy CDAHandle+2
- rts
-
- ;
- ; Private storage for OpenDAByUserID
- ;
-
- TheID dc.w 0 ; the user ID we're working on
- DANum dc.w 0 ; index for which NDA we're asking about
- CDANDAFlag dc.w 0 ; are we asking about CDAs or NDAs?
-
- DAInfoBuffer dc.w 0 ; returned data size
- NDAStatus dc.w 0 ; nonzero indicates an open NDA
- CDAHandle equ NDAStatus
- NDAOpen dc.l 0 ; open routine
- NDAClose dc.l 0 ; close routine
- NDAAction dc.l 0 ; action routine
- NDAInit dc.l 0 ; init routine
- NDAPeriod dc.w 0 ; period
- NDAEventMask dc.w 0 ; event mask
- NDATickCount dc.l 0 ; tick count at last run event sent to DA
- NDAWindPtr dc.l 0 ; NDA's main window pointer, if any
- NDAHandle dc.l 0 ; NDA handle
- NDAUserID dc.w 0 ; NDA's user ID (finally!)
-
- EndP
-
- EJECT
- *******************************************************************************
- *
- GiveMeMyFork PROCNAME
- *
- * Description: Returns quickly if our resource fork is already open.
- * If not, starts up the Resource Manager with our user
- * ID and opens our resource file. Stores the resource file
- * number in the global variable IRResFile.
- *
- * Inputs: None.
- *
- * Outputs: Our resource file number in IRResFile. Any GS/OS errors
- * in A with carry set, otherwise carry clear, A == $0000.
- *
- * External Refs:
- WITH IRData
- *
- * Entry Points:
- *
- *******************************************************************************
-
- ;
- ; If we get here, we're going to use resources, so save the current
- ; resource application first for later restoration.
- ;
- lda <OldResourceApp
- bne @GoodExit ; if we're here, we're done!
-
- pha
- _GetCurResourceApp
- pla
- sta <OldResourceApp
-
- lda IRResFile
- bne @GoodExit
-
- ; First, check the environment and see if we can do our thing.
-
- @GSOSHere lda >OS_BUSY
- bpl @WeCanGoOn
- bra @IRCantDoIt
- @IRCantDoIt lda #irGSOSNotAvail
- sec
- bra @rts
-
- @WeCanGoOn pushword IRUserID
- _ResourceStartUp ; we're logged in now
-
- lda #0
- pha ; space for result
- pushword #readEnable
- pha
- pha ; map address == NIL
- pha
- pha ; space for result
- pushword IRUserID
- pushword #$0001 ; file number one, always
- _LGetPathname2 ; leaves pointer to our file on stack
- _OpenResourceFile ; opens our resource file
- pla
- bcs @rts
-
- sta IRResFile
-
- @GoodExit pushword IRUserID
- _SetCurResourceApp ; redundant if we just started up
-
- lda #0
- clc
- @rts rts
-
- EndP
-
- EJECT
- *******************************************************************************
- *
- IRNotifyProc PROC
- *
- * Description: This is our notification procedure; GS/OS calls us when
- * switching to P8 so we can close our resource file and
- * be aware of it.
- *
- * Entry is PROC instead of PROCNAME because there's a
- * header we have to use.
- *
- * We also call this from srqGoAway to shut down our
- * Resource Manager stuff. Make sure to keep this in
- * mind if you ever change this routine.
- *
- *
- * Inputs: A,X,Y undefined
- *
- * Outputs: None
- *
- * External Refs:
- WITH IRData
- *
- * Entry Points:
- ENTRY NotifyProcCode
- *
- *******************************************************************************
-
- dc.l 0
- dc.w 0 ; reserved
- dc.w $A55A ; signature
- dc.l %10 ; switch GS/OS to P8 only
- Event_code dc.l 0 ; event code placed here
-
- NotifyProcCode NAME
-
- phb
- phk
- plb
-
- pha
- _GetCurResourceApp
- pla
- sta TempResourceApp ; can't store on stack frame, but this
- ; routine isn't reentrant anyway
- lda IRUserID
- pha
- _SetCurResourceApp
-
- lda IRResFile
- beq @NotifyOut
- pha
- _CloseResourceFile
-
- lda #0
- sta IRResFile
-
- _ResourceShutDown
-
- lda TempResourceApp
- pha
- _SetCurResourceApp ; restore this
-
- @NotifyOut plb
- rtl
-
- TempResourceApp dc.w 0
-
- EndP
-
- EJECT
- *******************************************************************************
- *
- DoAlertWindow PROCNAME
- *
- * Description: Takes an AlertWindow resource ID in X and Y and displays
- * that alert. Returns the button ID in A or $FFFF if
- * something went wrong.
- *
- * Verifies that the AlertWindow environment is present
- * before doing anything so callers don't have to worry
- * about that.
- *
- *
- * Inputs: AlertWindow resource ID in X and Y.
- *
- * Outputs: Button ID in A, or $FFFF if something went wrong.
- *
- * External Refs:
- *
- * Entry Points:
- *
- *******************************************************************************
-
- phy
- phx ; save these briefly
-
- pea 0 ; pre-zeroed
- _WindStatus
- pla
- bne @GetTheFork
- lda #$FFFF ; something's wrong
- bra @rts ; we can't play
-
- @GetTheFork jsr GiveMeMyFork
-
- pha
- pha ; space for result
- _GetCursorAdr
- pulllong CursorAdr ; save this locally
-
- _InitCursor
-
- plx
- ply
-
- lda #$FFFF
- pha ; space for result
- pea $0034 ; string is resource, no sub strings,
- ; use new button placement, use sound
- pha
- pha ; no substitution array
-
- phy
- phx ; resource ID
- _AlertWindow
-
- pushlong CursorAdr
- _SetCursor
-
- pla
-
- @rts rts
-
- CursorAdr dc.l 0 ; temporary cursor address
-
- EndP
-
- END
-
-
-
-